转载

iOS分享 - 对象间的通信之delegate、notificationCenter与block

在项目开发中,常常会涉及到对象之间的通信,而为了降低对象间的耦合,会采用delegate、notificationCenter、block三种方式来进行实现,对于他们的使用,也许大家都能熟练掌握,但是对于如何创建,初学者也许只是一知半解,本文不讲长篇大论,仅通过简单的实例来帮助大家学习三者的使用,希望对尚不了解以上三者的朋友能带来一定的帮助。

一、delegate

估计大家最常用的delegate就是UITableViewDelegate了,那么我们如何自己写一个代理呢?我们常常会在控制器中监听某个视图中按钮的点击,就以此为例。假如在DTestView中有一个Button,我们要在DTestViewController中对这个按钮的点击进行监听,并在点击Button时传递一个数组给DTestViewController,那么代码如下:

 //1、在DTestView.h文件中声明协议并创建协议方法 @class DTestView; @protocol DTestViewDelegate <NSObject> @optional /**点击按钮并传递数组信息*/ - (void)dTestViewDidClickBtn:(DTestView*)dTestView withArr:(NSArray *)position; @end  //2、在DTestView.h文件中声明delegate属性 @interface DTestView : UIView @property (nonatomic, weak) id <DTestViewDelegate> delegate; @end  //3、在DTestView.m文件中Button的点击事件里调用delegate的协议方法 - (void)btnClick {    if ([self.delegate respondsToSelector:@selector(dTestViewDidClickBtn:withArr:)]) {       NSArray *arr = @["test", "delegate"];       [self.delegate dTestViewDidClickBtn:self withArr:arr];   }          } 

创建代理总共就3步,怎么样,是不是很简单?但是这之中也有几个需要注意的地方:

1、命名规范:类名+Delegate。

2、@optional关键字:遵循协议后,该协议方法可以不实现,协议方法默认为@required修饰,即遵循协议后必须实现该方法,建议不是必须实现的方法都用@optional修饰。

3、ARC环境下,delegate属性用weak修饰。

4、在调用代理方法前,利用respondsToSelector:方法判断代理方法是否存在。

以上就是创建delegate时的注意事项,大家可以思考下为什么要这么做,如有不明白的地方,欢迎提问,如有不对的地方,欢迎指正。

接下来就是delegate的使用了,简单说下,也是3步:

 //1、设置代理 - (void)viewDidLoad {    [super viewDidLoad];    dTestView *view = [[dTestView alloc] init];    view.delegate = self;    [self.view addSubview:view];     }  //2、遵循协议 @interface DTestViewController ()<DTestViewDelegate>  //3、实现协议方法 - (void)dTestViewDidClickBtn:(DtestView *)dTestView withArr:(NSArray *)arr {    NSLog(@"%@", arr); } 

好了,这就是一个简单的delegate的创建与使用。

二、notificationCenter

通知中心相对简单,仍以监听按钮点击并传递一个数组为例,在NTestView中发布通知:

 //在Button的addTarget点击事件中发布通知 - (void)btnClick {    NSArray *arr = @[@"test", @"notificationCenter"];    [[NSNotificationCenter defaultCenter] postNotificationName:@"点击按钮" object:nil userInfo:arr]; } 

完了?完了,就这么简单,接下来在NTestViewController中添加观察者:

 //添加观察者 - (void)viewDidLoad {    [super viewDidLoad];    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(nTestViewDidClickBtn:) name:@"点击按钮" object:nil]; } /**接收到通知时调用该方法*/ - (void)nTestViewDidClickBtn:(NSNotification *)note {    NSArray *arr = note.userInfo;    NSLog(@"%@", arr); }  //移除观察者 - (void)dealloc {     [[NSNotificationCenter defaultCenter] removeObserver:self]; } 

解释一下参数:

name:通知的名称

object:需要传递的对象

userInfo:发布通知是传递的信息(添加观察者时,默认可以接收该参数)

以上,就是notificationCenter的简单使用。 注意:在不需要监听时,一定要移除观察者

三、block(闭包)

block的简单使用,仍以监听按钮点击并传递一个数组为例:

 //1、在BtestView.h文件中,我们可以提供这样一个类方法用于初始化: @interface BTestView : UIView /**block属性*/ @property(nonatomic,copy) void(^arrBlock)(NSArray *);  /**初始化方法*/ + (instancetype)bTestViewWithArrBlock:(void(^)(NSArray *arr))arrBlock; @end  //2、在BTestView.m文件中,实现该方法: + (instancetype)bTestViewWithaArrBlock:(void(^)(NSArray *arr))arrBlock {     BTestView *view = [[BTestView alloc] init];     _arrBlock = arrBlock;     return view; }  //3、在Button的addTarge点击事件中调用arrBlock - (void)clickBtn {   NSArray *arr = @[@"test", @"notificationCenter"];   _arrBlock(arr);  } 

在NTestViewController中使用block:

 - (void)viewDidLoad {    [super viewDidLoad];    BTestView *view = [BTestView bTestViewWithArrBlock:^(NSArray *arr){     NSLog(@"%@", arr);   }];    [self.view addSubview:view];  } 

不知道大家看到block用法的时候有没有一种熟悉感?

注意:block属性要用copy修饰,同时,在使用的时候要注意不要造成循环引用。

至于这三种通信方式具体要用哪一种?这必须结合实际项目才能做出选择,常见的一种说法是:一对多通信用notificationCenter,一对一通信在方法少的情况用block,方法多的情况用delegate。

注意:以上代码均未通过实际测试,本文仅提供简单的使用思路。

正文到此结束
Loading...