转载

IOS开发学习笔记044-通知和代理(观察者模式和代理模式)

处理文本输入框的输入事件,单击文本输入框后要弹出键盘。

弹出键盘有两种实现方式:一种代理,一种通知。也就是对应的(观察者模式和代理模式)。

1、通知

1.1、准备工作

实现过程:先注册消息  postNotificationName  ,然后在响应的方法的接收消息  addObserver, 最后实现接收消息的方法

  因为在系统中又定义好的键盘处理通知, 所以直接进行监听就行了。

         UIKIT_EXTERN NSString * const UIKeyboardWillShowNotification; // 即将弹出

         UIKIT_EXTERN NSString * const UIKeyboardDidShowNotification; // 显示

         UIKIT_EXTERN NSString * const UIKeyboardWillHideNotification;   //即将隐藏

         UIKIT_EXTERN NSString * const UIKeyboardDidHideNotification; // 隐藏         

1.2、实现过程

//  1、 通过通知监听键盘出现消息

//  添加监听器,监听键盘弹出

[[ NSNotificationCenter defaultCenter addObserver : self selector : @selector (keyboardComeout:)  name : UIKeyboardWillShowNotification object : nil ];

//  添加监听器 , 监听键盘退出

[[ NSNotificationCenter defaultCenter addObserver : self selector : @selector (keyboardGoaway:)  name : UIKeyboardWillHideNotification object : nil ];

 

// 2、 响应通知的方法,显示键盘

- ( void )keyboardComeout:( NSNotification *)note

{

NSLog ( @"keyboardComeout--/n%@" ,note);

//  取出消息中键盘出现后的最终位置 , 要将字典对象转换成 CGRect

CGRect  rect = [note. userInfo [ UIKeyboardFrameEndUserInfoKey CGRectValue ];

self . viewBotom . constant  = rect. size . height ;

//  取出键盘弹出所需要的时间

double  animateTime = [note. userInfo [ UIKeyboardAnimationDurationUserInfoKey doubleValue ];

[ UIView animateWithDuration :animateTime  animations :^{

[ self . view layoutIfNeeded ];

}];

/**

*   NSNotification 内部信息

NSConcreteNotification 0x7f896bebf4d0 {name = UIKeyboardWillShowNotification; userInfo = {

UIKeyboardAnimationCurveUserInfoKey = 7;

UIKeyboardAnimationDurationUserInfoKey = "0.25";

UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {375, 225}}";

UIKeyboardCenterBeginUserInfoKey = "NSPoint: {187.5, 779.5}";

UIKeyboardCenterEndUserInfoKey = "NSPoint: {187.5, 554.5}";

UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 667}, {375, 225}}";

UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 442}, {375, 225}}";

}}

*/

}

/**

*  3、 开始滚动界面后隐藏键盘

*/

- ( void )scrollViewWillBeginDragging:( UIScrollView *)scrollView

{

// 退出键盘

//  NSLog ( @"scrollViewWillBeginDragging--" );

//[self.view endEditing:YES];//方法1

[ self . textField  resignFirstResponder ];  // 方法2: 谁响应的键盘,谁就可以调用这个方法退出键盘 (resignFirstResponder)

}

//  隐藏键盘

- ( void )keyboardGoaway:( NSNotification *)note

{

NSLog ( @"keyboardGoaway--/n%@" ,note);

self . viewBotom . constant0 ;

// 取出键盘弹出所需要的时间

double  animateTime = [note. userInfo [ UIKeyboardAnimationDurationUserInfoKey doubleValue ];

[ UIView animateWithDuration :animateTime  animations :^{

[ self . view layoutIfNeeded ];

}];

}

弹出 效果,实际效果是有动画的,过渡更好。

IOS开发学习笔记044-通知和代理(观察者模式和代理模式)

1.3、键盘弹出后还要对真个View进行上移,隐藏后下移

  这里使用更新控件的约束来实现view的移动

IOS开发学习笔记044-通知和代理(观察者模式和代理模式)

如下属性:

@property ( weak nonatomic IBOutlet NSLayoutConstraint  *viewBotom;

然后控制约束的constant值,就可以实现view的移动。

设置方法方法:

//  取出消息中键盘出现后的最终位置 , 要将字典对象转换成 CGRect

CGRect  rect = [note. userInfo [ UIKeyboardFrameEndUserInfoKey CGRectValue ];

self . viewBotom . constant  = rect. size . height ;      

1.4、给UITextField 两边添加一个间距

直接使用其自带的功能即可

//  设置文本框左边的内容

UIView *leftView = [[ UIView allocinit ];

leftView. frameCGRectMake ( 00100 );

self . messageField . leftView = leftView;

self . messageField . leftViewMode  =  UITextFieldViewModeAlways ;

//  右边间距

self . messageField . rightView = leftView;

self . messageField . rightViewMode  =  UITextFieldViewModeAlways ;

1.5、使用完毕后要手动删除监听器

- ( void )dealloc

{

// 使用完毕后要手动移除监听对象

[[ NSNotificationCenter defaultCenter ] removeObserver : self ];

}

2、代理模式

2.1、使用注意事项

1、在头文件中实现代理,定义协议

2、使用方法:1 设置代理,2 遵守协议,3 实现方法

3、规范:参考苹果官方的协议实现方式

4、作用:

1、监听事件:A是监听B的一些行为,则A成为B的代理

2、消息传递:A想告诉B一些事情,则B成为A的代理

5、总结:

1、如果想监听别人的一些行为,那么就要成为别人的代理

2、如果你想告诉别人一些事情,那么就让别人成为你得代理

6、开发步骤

1、拟一份协议(格式:控件名 + Delegate),在协议里声明一些代理方法(一般代理方法都是@optional)

2、声明一个代理属性(弱引用) @property (weak,nonatomic) id delegate;

3、在内部发生某些行为时,调用代理对应的代理方法,通知代理内部发生了什么事情

4、设置代理: xxx.delegate = self;

5、 yyy对象遵守协议,实现代理方法

2.2、代码实现

先看效果

IOS开发学习笔记044-通知和代理(观察者模式和代理模式)

首先在xib里实现界面如下:

IOS开发学习笔记044-通知和代理(观察者模式和代理模式)

然后实现文件也比较简单,在点击过加载按钮后,由此对象给代理发送加载数据通知。

头文件实现里包括代理所遵守协议的定义,包括一个可用方法。

@class SLQLoadData ;

@protocol SLQLoadDataDelegate < NSObject >

@optional

/**

代理方法:点击按钮操作

*/

- ( void )LoadDataDidCilckButton:( SLQLoadData *)loadData;

@interface SLQLoadData : UIView

// 代理属性

@property ( weak , nonatomic ) id < SLQLoadDataDelegate > delegate;

+ ( instancetype )loadData; // 返回加载对象

- ( void )endingloadData; // 结束加载

@end

#import "SLQLoadData.h"

@interface SLQLoadData ()

- ( IBAction )loadMoreData:( id )sender;

@property ( weak , nonatomic ) IBOutlet UIView *loadView; // 正在加载界面

@property ( weak , nonatomic ) IBOutlet UIButton *loadBtn; // 加载按钮

@end

@implementation SLQLoadData

+ ( instancetype )loadData

{

// NSStringFromClass 将类名转换成字符串 ,xib 文件名和类名一样

return [[[ NSBundle mainBundle ] loadNibNamed : NSStringFromClass ( self ) owner : nil  options : nil ] lastObject ];

}

- ( IBAction )loadMoreData:( id )sender

{

// 模拟从网络加载数据

// NSLog ( @“loadMoreData” );

self . loadView . hidden = NO ;

self . loadBtn . hidden = YES ;

// 发送消息到代理对象 , 首先判断代理方法是否存在

if ([ self . delegate respondsToSelector : @selector (LoadDataDidCilckButton:)])

{

[ self . delegate   LoadDataDidCilckButton : self ]; 

}

}

// 隐藏正在加载界面

- ( void )endingloadData

{

self . loadView . hidden = YES ;

self . loadBtn . hidden = NO ;

}

@end

2.3、控制器中对代理方法的使用

1、包含头文件并遵守协议

#import "SLQLoadData.h"

@interface ViewController () < SLQLoadDataDelegate > // 遵守代理协议

2、指定代理对象

SLQLoadData *loadData = [ SLQLoadData  loadData ];

// 指定控制器为代理对象

loadData. delegate = self ;

self . tableView . tableFooterView = loadData;

3、实现代理方法

// 实现代理方法

- ( void )LoadDataDidCilckButton:( SLQLoadData *)loadData

{

NSLog ( @"LoadDataDidCilckButton" );

// 模拟从网络加载数据 , 加一个定时器

dispatch_after ( dispatch_time ( DISPATCH_TIME_NOW , ( int64_t )( 2.0 * NSEC_PER_SEC )), dispatch_get_main_queue (), ^{

SLQFengNews *news = [[ SLQFengNews alloc ] init ];

news. title = @" 高考往事 " ;

news. topic = NO ;

news. image = @"ad_02" ;

news. comment = @"13489" ;

// 添加至模型对象

[ self . news addObject :news];

// 刷新表格

[ self . tableView reloadData ];

// 隐藏 loadView

SLQLoadData *load = ( SLQLoadData *) self . tableView . tableFooterView ;

[load endingloadData ];  

});

}

2.4、最终效果 -_-

IOS开发学习笔记044-通知和代理(观察者模式和代理模式)

总结:代理和通知的区别

代理:一对一

通知:多对多

正文到此结束
Loading...