代理這東西,真的不想再談了,估計是個iOS開發人員都能熟練使用,跟Notification和Block一樣,都用的滾瓜爛熟了。 這裡小小的談論一下代理的擴展:隱式代理和多播代理,其實非常簡單。 隱式代理:就是定義協議的屬性時不用再遵守協議了,實現方法的類也不用在遵守協議了,因為協議方法定義在NSOb ...
代理這東西,真的不想再談了,估計是個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、通知的參數通過UserInfo來傳遞,UserInfo是一個字典,也容易寫錯;
3、通知是單向的,代理是雙向的,有返回值;
4、通知的邏輯不清晰。
思路:其實就是定義一個代理屬性,只不過這個代理屬性是一個數組而已,然後對外提供一個方法添加元素至這個數組中。然後調用對象方法的時候,迴圈遍歷這個屬性(數組類型)即可。理解了這點,也就很輕鬆了。
說了這麼多,說的我自己都迷糊了,不如直接上代碼來的痛快。反正代碼很少,就不解釋了。
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呢。