delegate、NSNotification、block三者的比较

  在开发过程中,我们经常会遇到不同的页面之间进行数据传递等方式的通信。在本人的开发过程中,比较常遇到的方式有: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的循环引用。

对于三者的理解,还有所欠缺,欢迎大家来指正
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值