在开发过程中,我们经常会遇到不同的页面之间进行数据传递等方式的通信。在本人的开发过程中,比较常遇到的方式有:delegate委托;NSNotification 通知;block形式。
那这三种方式应该选择哪种方式呢?
1、delegate 委托
在开发的过程中,我们会接触到很多的delegate委托。在UITableView的使用中,在UITextView 、UITextField中,都用到了这种方式。
介绍:
委托是比较灵活的模式之一。它的功能是程序中的一个对象代表另一个对象,或者一个对象与另外一个对象协同工作。
作用:
在开发当中,用到delegate委托主要有两种方式,一种是值传递,另一种是事件传递。
1、值传递就是在b类中的某个变量发生变化后,a类需要根据相应的变化做出处理。
2、事件传递是指在b类发生了某个事件之后,需要把这个事件传递给a类,让a类根据事件的发生做出反应。
在demo中, 点此下载
创建了两个页面FirstViewController和SecondViewController,我们想将SecondViewController 页面当中的textView在完成文本输入后传递给FirstViewController
使用delegate委托的方式,首先定义代理SecondViewDelegate,并定义方法:- (void)transportTextOfView:(NSString *)text;
@protocol SecondViewDelegate <NSObject>
- (void)transportTextOfView:(NSString *)text;
@end
代理声明:
@interface SecondViewController : UIViewController
@property (assign,nonatomic) id<SecondViewDelegate>delegate;
@end
在点击“完成”按钮时,我们来通过委托发送消息
- (void)textDoneButtonItem
{
if ([self.delegate respondsToSelector:@selector(transportTextOfView:)]) {
[self.delegate transportTextOfView:textView.text];
}
[self.navigationController popViewControllerAnimated:YES];
}
接下来,我们在FirstViewController 中设置代理
- (void) pushToNextViewControllerWithDelegate
{
SecondViewController *secondViewCon = [[SecondViewController alloc] init];
secondViewCon.delegate = self;
[self.navigationController pushViewController:secondViewCon animated:YES];
}
实现代理方法:
- (void)transportTextOfView:(NSString *)text
{
if (text.length) {
textView.text = text;
textView.frame = MainScreen;
CGPoint center = textView.center;
center = self.view.center;
textView.center = center;
}
}
这样我们就利用delegate委托的方式将SecondViewController页面textView中的文本信息传递到了FirstViewController,并在页面上进行了展示
2、NSNotificationCenter 通知机制
NSNotificationCenter 是一种同步的消息通知机制,观察者在消息中心注册,就可以接受其他对象发来的消息,并且消息的发送者和处理者之间可以完全独立。
NSNotificationCenter 消息通知可以在同一时间实现一对多的消息通知。
我在使用时,比较多使用消息通知机制的情境有:app后台获取数据后刷新前台显示UI,一个页面的某个变量改变时引起其他多个页面的改变等。
在demo中,我们利用NSNotificationCenter 消息通知机制来监控键盘的弹出及隐藏,从而改变textView的frame。首先我们需要注册消息通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationInfo:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationInfo:) name:UIKeyboardWillHideNotification object:nil];
利用的方法是
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
observer:观察者,一般都是类本身,即self
aSelector:处理消息的方法名,在demo中为notificationInfo:
aName:进行消息通知时的标记,编译器可以通过aName找到需要通知的类
object:传递的参数,在进行注册时,通常设为nil
实现处理消息的方法
- (void)notificationInfo:(NSNotification *)notification
{
if ([notification.name isEqualToString:UIKeyboardWillShowNotification]) {
NSDictionary *userInfo = notification.userInfo;
NSValue *value =userInfo[@"UIKeyboardBoundsUserInfoKey"];
CGSize size = [value CGRectValue].size;
CGRect rect = textView.frame;
rect.size.height = MainScreenHeight - size.height;
[UIView animateWithDuration:0.5f animations:^{
textView.frame = rect;
}];
}
else
{
[UIView animateWithDuration:0.5f animations:^{
textView.frame = MainScreen;
}];
}
}
这样在键盘弹出和隐藏时就可以检测到,从而改变textView的frame改变。
3、block
block是在IOS4.0之后新增的程式语法。
block适用的场景:
任务完成时回调(比较多用于网络数据的异步请求)
处理消息监听回调处理
错误回调处理
枚举回调
试图动画转换
排序
在demo中,我们用到的是处理消息监听回调处理,也就是在点击“完成”按钮时,实现delegate委托实现的功能。
首先创建一个全局的block
typedef void (^SecondTextBlock)(NSString *text);
这个block 命名为SecondTextBlock,需要传递变量 text,返回值为void
在SecondViewController声明方法
- (instancetype)initWithTextBlock:(SecondTextBlock)textBlock;
并实现方法
- (instancetype)initWithTextBlock:(void (^)(NSString *text))textBlock
{
self = [super init];
if (self) {
selfBlock = textBlock;
}
return self;
}
并在点击“完成”按钮时,实现block方法
- (void)textDoneButtonItem
{
if (selfBlock) {
selfBlock(textView.text);
}
[self.navigationController popViewControllerAnimated:YES];
}
在FirstViewController 中,使用
- (void)pushToNextViewControllerWithBlock
{
__weak FirstViewController *weakSelf = self;
SecondViewController *secondViewCon = [[SecondViewController alloc] initWithTextBlock:^(NSString *text)
{
[weakSelf transportTextOfView:text];
}];
[self.navigationController pushViewController:secondViewCon animated:YES];
}
这样,就可以利用block的形式进行页面之间的值传递
三者之间的比较
1、delegate 是一种one - to - one 的方式实现信息处理,比较适合由于一个类改变而引起另一个类改变的事件传递或值传递
缺点是利用delegate委托需要定义的代码比较多,协议的制定,delegate属性的创建,以及delegate方法的实现
2、NSNotificationCenter 消息通知机制 是一种one - to - one / more /none的机制,可以将消息告知一个或多个类进行更改。而且书写简单,不需要实现太多代码。
缺点则是在编译时不会检查通知是否会被观察者正确的处理;观察者注册和取消注册是一对一存在;
在调试时,应用的工作及控制过程比较难跟踪;
3、block 是比较强大的、封闭性很好的信息传递方式。本人在使用的过程中,感觉block使用起来会非常的方便,不需要创建太多的代码,更改起来相对方便。但是缺点也比较明显,如果在不同的页面之间利用block进行信息传递,在进行调试时比较难跟踪到block 最终实现的方法,如果页面比较烦杂,很容易就会错误的使用block,从而造成block的循环引用。
对于三者的理解,还有所欠缺,欢迎大家来指正