zoukankan      html  css  js  c++  java
  • 代理扩展-隐式代理和多播代理

    代理这东西,真的不想再谈了,估计是个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呢。

  • 相关阅读:
    linux日常管理-rsync后台服务方式-1
    linux日常管理-rsync_ssh方式
    linux日常管理-rsync常用选项详解
    linux日常管理-rsync格式
    socket 服务端 | socket 客户端 -->黏包现象
    udp 服务端 | udp 客户端 --循环发消息
    udp 协议 服务端 | udp 客户端
    socket tcp 服务端 | socket tcp 客户端 -->之循环
    socket tcp 服务器 | socket tcp 客户端
    计算器写法 | '1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
  • 原文地址:https://www.cnblogs.com/panda1024/p/6031619.html
Copyright © 2011-2022 走看看