代理这东西,真的不想再谈了,估计是个iOS开发人员都能熟练使用,跟Notification和Block一样,都用的滚瓜烂熟了。
这里小小的谈论一下代理的扩展:隐式代理和多播代理,其实非常简单。
隐式代理:就是定义协议的属性时不用再遵守协议了,实现方法的类也不用在遵守协议了,因为协议方法定义在NSObject的分类中。
直接上代码吧,真的是十分的简单:
1、Person类的头文件:
1 #import <Foundation/Foundation.h> 2 3 /** 4 NSObject的一个分类,里面声明(代理)方法 5 */ 6 @interface NSObject(myfenlei) 7 8 - (void)eat; 9 10 @end 11 12 /** 13 定义一个类 14 */ 15 @interface Person : NSObject 16 17 @property(nonatomic,copy) NSString *name; 18 19 /** 20 代理属性,不用尊守协议,因为要实现的是NSObject分类的方法 21 */ 22 @property(nonatomic,weak) id delegate; 23 24 - (void)run; 25 26 @end
2、Person类的.m文件:
1 #import "Person.h" 2 3 @implementation Person 4 5 - (void)run{ 6 NSLog(@"%@在跑步",self.name); 7 8 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 9 if([self.delegate respondsToSelector:@selector(eat)]){ 10 // 调用代理对象的eat方法(声明在NSObject的分类里面) 11 [self.delegate eat]; 12 } 13 }); 14 } 15 16 @end
3、控制器中调用Person对象的run方法,run方法里面调用代理方法:
1 #import "ViewController.h" 2 #import "Person.h" 3 4 @interface ViewController () 5 6 @end 7 8 @implementation ViewController{ 9 Person *_per; 10 } 11 12 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ 13 _per = [[Person alloc] init]; 14 _per.name = @"小明"; 15 _per.delegate = self; // 指定代理 16 [_per run]; // 调用方法,方法里面调用代理方法 17 } 18 19 /** 20 实现协议方法 21 */ 22 - (void)eat{ 23 NSLog(@"跑完了,准备吃饭呢"); 24 } 25 26 @end
完事了,没有了。隐式代理就是这么的简单。其中强调一下,最最最重要的是协议方法定义在了NSObject的分类中。理解了这点,是不是很easy呢。
下面:我们再来谈谈多播代理。
多播代理和通知很像,一个对象发出消息,多个对象监听。但比通知好用:1、通知的Key容易写错;2、通知的逻辑不清晰。
思路:其实就是定义一个代理属性,只不过这个代理属性是一个数组而已,然后对外提供一个方法添加元素至这个数组中。然后调用对象方法的时候,循环遍历这个属性(数组类型)即可。理解了这点,也就很轻松了。
说了这么多,说的我自己都迷糊了,不如直接上代码来的痛快。反正代码很少,就不解释了。
1、Person类头文件:
1 #import <Foundation/Foundation.h> 2 3 /** 4 定义协议,声明方法 5 */ 6 @protocol PersonDelegate <NSObject> 7 8 - (void)eatSomething; 9 10 @end 11 12 13 @interface Person : NSObject 14 15 /** 16 添加代理的方法 17 18 @param delegate <#delegate description#> 19 */ 20 - (void)addDelegate:(id)delegate; 21 22 - (void)eat; 23 24 @end
2、Person类.m文件:
1 #import "Person.h" 2 3 @interface Person () 4 5 /** 6 代理成员变量,是一个数组 7 */ 8 @property (nonatomic, strong) NSMutableArray *delegates; 9 10 @end 11 12 @implementation Person 13 14 // 给代理数组添加元素 15 - (void)addDelegate:(id)delegate{ 16 [self.delegates addObject:delegate]; 17 } 18 19 // 关键方法:调用对象方法时,遍历数组,今次执行方法 20 - (void)eat{ 21 for (id delegate in self.delegates) { 22 [(id)delegate eatSomething]; 23 } 24 } 25 26 // 懒加载,初始化代理属性数组 27 - (NSMutableArray *)delegates{ 28 if (_delegates == nil) { 29 _delegates = [NSMutableArray array]; 30 } 31 return _delegates; 32 } 33 34 @end
3、好了,接下来我们看看具体是怎么使用的:
1 OneViewController *oneVc =[[OneViewController alloc] init]; 2 TwoViewController *twoVc = [[TwoViewController alloc] init]; 3 4 Person *per = [Person new]; 5 6 //设置多播代理 7 [per addDelegate:oneVc]; 8 [per addDelegate:twoVc]; 9 10 //调用代理方法 11 [per eat];
4、看到了吧,就是调用方法给代理属性(数组)中添加元素,然后调用eat方法时,遍历数组,执行方法。这里
OneViewController和TwoViewController都实现了协议里面的- (void)eatSomething;方法。
1 // OneViewController 2 #import "OneViewController.h" 3 4 @interface OneViewController () 5 6 @end 7 8 @implementation OneViewController 9 10 - (void)eatSomething{ 11 12 NSLog(@"one"); 13 } 14 15 @end 16 17 // TwoViewController. 18 #import "TwoViewController.h" 19 20 @interface TwoViewController () 21 22 @end 23 24 @implementation TwoViewController 25 26 - (void)eatSomething{ 27 28 NSLog(@"two"); 29 } 30 31 @end
好了,就是这样,是不是很easy呢。