系列:iOS开发-协议和代理

181 阅读7分钟

#系列:iOS开发-协议和代理 既然说到了协议和代理,那么就有必要解释下意思. 协议: 协议是一个方法签名的列表,在这个列表中可以定义若干个方法而根据配置,那些遵守这个协议的类就会去实现这个协议中规定的若干个方法. 那什么又是代理呢?

举一个简单的例子. 隔壁老王最近新开了一家便利店,因为是新开张的,所以老王自己承担了所有的工作,其中包括,进货、上架、收银... 这样我们大致可以写出来一个类, 我们暂定老王是一个BOSS类,毕竟便利店是他开的蛮... 那么它就有相应的三个方法,进货,上架,和收银

这里写图片描述
因为便利店毕竟刚刚开起来,所有的事情没有办法,只能他自己亲力亲为.. 那么我们可以看到这样的例子
这里写图片描述
老王一个人真的很累.... 但是功夫不负有心人,老王生意做大了 那么他就想到了扩展门店,把生意再做大,那么老王就想着说,招聘一个采购员,招聘一个管理员,招聘一个收银员,然后把手头的工作分给专门的人来干,这样老王只要收钱就好了, 说干就干,贴出招聘信息给猎头,猎头就根据需要帮他找到了三个专职员工, 张三,李四,王五 老王跟张三说,你只管采购货物,采购好了跟我说一声就OK 老王跟李四说,你只管上架货物,搞定后也是跟我说一声就好了 老王跟王五也说,你最重要,你负责收银,不能马虎,每天都要报备的! 于是就有了这样的三个类 我们分别看看, 张三:
这里写图片描述
这里写图片描述

我们分析一下,采购员有一个方法采购,我们在具体实现中可以看到,它干了两件事,第一件事负责采购工作,第二件是完成工作向上级汇报 这里的向上级汇报就是一个协议, 我们可以理解成我们工作的工作报告,每天工作完成了,都会写工作报告,会上交,但是至于上司看不看那是他的事,我们就不管了,如果他想看,那么他就跟我说需要我的报告,那么我就会把报告交给他

至于管理员和收银员也都类似这里就不展示了, 那么我们看看现在的老王是怎么干的,

//
//  Boss.m
//  DEMO_协议和代理
//
//  Created by charles on 2017/4/11.
//  Copyright © 2017年 charles. All rights reserved.
//

#import "Boss.h"
#import "Buyer.h"
#import "Keeper.h"
#import "Cashier.h"

@interface Boss ()<BuyerDelegate,KeeperDelegate,CashierDelegate>

@property (nonatomic, strong)Buyer *zhangsan;
@property (nonatomic, strong)Keeper *lisi;
@property (nonatomic, strong)Cashier *wangwu;
@end

@implementation Boss
- (instancetype)init
{
    self = [super init];
    if (self) {
        NSLog(@"开始招聘\n");
        [self recruit];//开始招聘
    }
    return self;
}
/**
 开始招聘
 */
-(void)recruit{
    _zhangsan = [[Buyer alloc]init];
    _zhangsan.delegate = self;
    NSLog(@"找到一个采购员,张三\n");
    
    _lisi = [[Keeper alloc]init];
    _lisi.delegate = self;
    NSLog(@"找到一个管理员,李四\n");
    
    _wangwu = [[Cashier alloc]init];
    _wangwu.delegate = self;
    NSLog(@"找到一个收银员,王五\n");
    
    NSLog(@"完成招聘\n");
    
    NSLog(@"开始工作\n");
    [self startWork];
}

-(void)startWork{
    NSLog(@"老王:张三去采购吧\n");
    [_zhangsan replenish];
}
/**
 张三完成了采购
 */
-(void)finishReplenish{
    NSLog(@"老王:张三你可以休息了,我叫李四上架\n");
    NSLog(@"老王:李四上架去吧\n");
    [_lisi shelves];//李四上架
}
/**
 李四完成了上架
 */
-(void)finishShelves{
    NSLog(@"老王:李四你也可以休息了\n");
    NSLog(@"老王:接下来的收银工作都交给你了,王五\n");
    [_wangwu cashier];//王五开始收银
}
/**
 王五完成了收银
 */
-(void)finishCahsier{
    NSLog(@"老王:王五,辛苦了一天,早点回家吧");
}


@end

这是招聘员工的老王, 老王是老板,手下有个员工叫做张三,老王叫张三去做采购工作的时候直接就把任务分给张三,张三接到任务之后开始采购,但是老王并不知道张三什么时候完成采购工作,所以老王要等待张三的电话,此时老王充当代理的角色,等待采购完成的信号,以此来分配下一步的工作, 所以就有了_zhangsan.delegate = self; 大意就是老王等待张三工作完成的信号,或者说老王等待张三的工作报告. 而因为老王选择了等待张三的报告,所以如果有报告上交,老王就能收到,

-(void)finishReplenish{
    NSLog(@"老王:张三你可以休息了,我叫李四上架\n");
    NSLog(@"老王:李四上架去吧\n");
    [_lisi shelves];//李四上架
}

OK 开始工作,我们此时看看所有的输出....

这里写图片描述
所有的员工严格按照老王的指示,各司其职... 老王只要看看报告,分配工作就好了,剩下的就等着数钱了....

那么为什么我们要这么做?

iOS中代理模式通常用于解决类似这样的问题:我们通过界面A打开了界面B,但在应用进行的过程中,界面B有时候也需要和A主动联络,比如点击某个按钮时。一个比较好的办法是,让A成为B的代理,这样B就可以在需要的时候给A发送消息了。

放到我们上面的例子就是A就是老王,B就是张三,老王招聘了张三,老王可以直接分配工作给张三,但是张三天天在外面采购,采购完成之后需要和老王主动联系,这时让老王成为张三的代理,这样张三完成采购之后就能够给老王发送消息了

代理模式的一个好处是,B实际上不需要了解A的任何事情,只要知道A是自己的代理就可以了。在这种模式下,B依然独立与A,实现了松耦合。

对象A是对象B的代理,对象B需要向A发送消息,设置方法分四步: 1、在对象B的.h中定义一个protocol代理协议,并声明一个协议的属性变量

这里写图片描述
2、让对象B在适当的时候向代理对象A发送消息,比如触发按钮时(比如张三采购完成之后)。
这里写图片描述
3、让对象A遵从代理协议
这里写图片描述
4、通知对象B,现在A是它的代理
这里写图片描述

此外,上面的老王开便利店用来做例子只是我对代理和协议的一种方便理解的方式,当然网上还有很多其他的例子,大家也可以拿来做参考,但是总的来说大致的意思都是一样的.

我们在回到之前的UITextField来说说,

首先我们在vc类中创建并添加了一个UITextField的对象,我可以直接方便的给这个对象赋值,输入文字,但是这个对象什么时候结束编辑,什么时候文字改变了...这些我是没有办法直接方便的获取的,另外虽然UITextField本身是明确的知道的它自身的这些状态的变化,可是它也不知道要干什么事情,这样就两难了,我想要获取这些信息,并在这些状态改变的时候干些事情,于是UITextField指定了一套协议,而我也就是当前的vc如果遵守了这个协议,并且获得了代理, 那么当这些状态发生变化的时候,他们就会跟我说:你可以干某些事了... 对应到上面的说明中去就是: A:self B:textField B不需要管A,只要跟A说,我的状态变了,你自己看着办, A获取到变化的信息,做出相应的操作.....

当然,代理作为一种设计模式,在iOS中的应用是很广泛的,很多系统的类都会用到,我们在开发的时候很多反向传值等也会用到,我们自定义控件等会用到..... 所以也不要太担心,用着用着,你就熟悉了....

Demo地址:github.com/spicyShrimp…

系列:iOS开发-前言+大纲 blog.csdn.net/spicyShrimp…