上一篇的地址为: IOS Protocol与Delegate详解(一)
上一篇讲了协议的最基本用法,这一次讲协议更重要的地方:回调协议
回调协议(委托)
在我的理解中,所谓的委托,其实就是回调协议的意思,也就是说委托就是一个非常强大的依靠协议的设计模式,所以有人说,在OC中,委托是协议的一部分
为什么说委托是及其重要的概念呢,例如在网络请求的时候,我们得主UI线程不知道分线程什么时候从网络上面请求回完整的数据,而且也有可能失败,这样做最简单得方法就是,自定义一个委托协议,并让主UI线程的类实现此委托,将自己这个委托对象传递给网络请求的类,这样,不管网络请求成功或失败,网络请求类都可以回调相应的委托来解决
不仅仅是网络请求,当多线程操作,数据库操作,类间通信都极有可能用到这种设计模式
下面举一个生活中的例子来解释一个委托
比如说有一个领导,旁边有他得秘书小李,有一天,领导给小李说:"小李啊,没茶叶了,你给我弄点上好茶叶去,如果弄回来了,我就给你涨工资,如果没弄上,就去站墙根去。"
上面的例子可以这么解释,领导与小李之间有一个"弄茶叶"协议,"弄茶叶"协议中有两个方法(也可以理解为事件),一个是"弄回来了"方法,一个是"没弄回来"方法,而领导就是这个这两个方法的制定者,但是小李却是这两个方法的执行者,听懂了吗?
其实最简单得理解就是先把方法都抽象出来,然后将其组成一个协议,弄清谁是这个协议的制定者,上述中,领导说的这句话,制定了规矩(协议),其实就是实现了协议,但是谁执行呢,总不能领导站墙根吧,所以执行者是小李。
抽象完毕,其实就是领导和小李之间有一个"弄茶叶"协议,领导实现了此协议,小李去弄茶叶,然后根据情况回调不同得协议方法,所以,领导是小李的委托对象
说了这么多,可能有些人已经懵了,所以,通过例子来解答
下面是得到茶的协议:
#import <Foundation/Foundation.h>
@protocol GetTeaDelegate <NSObject>
@required
/**
成功得到茶的方法
*/
-(void) getTeaSuccess;
/**
没有得到茶的方法
*/
-(void) getTeaFail;
@end
领导类的.h文件:
#import <Foundation/Foundation.h>
#import "GetTeaDelegate.h"
@interface Leader : NSObject<GetTeaDelegate>{
}
@end
领导类的.m文件
#import "Leader.h"
@implementation Leader
/*
现在是以领导的角度来实现这个协议
规定小李在不同的情况下该干什么
*/
/**
成功的得到茶
*/
-(void) getTeaSuccess{
NSLog(@"不错不错,这月给你涨工资");
}
/**
没拿到茶
*/
-(void) getTeaFail{
NSLog(@"站墙角去!");
}
@end
#import <Foundation/Foundation.h>
#import "GetTeaDelegate.h"
@interface Worker : NSObject{
}
//小李的得到茶的代理
@property (nonatomic) id<GetTeaDelegate> myGetTeaDelegate;
/**
需要传入一个实现了得到茶这个协议的对象来做自己的代理,方便完成或失败后回调
*/
-(Worker *) initWithDelegate:(id<GetTeaDelegate>) delegate;
/*
模拟去得到茶的方法
*/
-(void) goToGetTea;
@end
职工类的.m文件
#import "Worker.h"
@implementation Worker
/**
需要传入一个实现了得到茶这个协议的对象来做自己的代理,方便完成或失败后回调
*/
-(Worker *) initWithDelegate:(id<GetTeaDelegate>) delegate{
self=[super init];
if (self) {
self.myGetTeaDelegate = delegate;
}
return self;
}
/*
模拟去得到茶的方法
*/
-(void) goToGetTea{
NSLog(@"弄茶中...");
//声明一个定时器,让其5秒钟之后执行successToGetTea(假设成功得到了茶),来模拟得到茶的过程
NSTimer *timer=[NSTimer scheduledTimerWithTimeInterval:5.0f target:self selector:@selector(successToGetTea) userInfo:nil repeats:NO];
}
/*
模拟得到茶成功的方法
*/
-(void)successToGetTea{
//判断代理是否为空
if (self.myGetTeaDelegate) {
//回调代理的方法
[self.myGetTeaDelegate getTeaSuccess];
}
}
/*
模拟得到茶失败的方法
*/
-(void) failToGetTea{
//判断代理是否为空
if (self.myGetTeaDelegate) {
//回调代理的方法
[self.myGetTeaDelegate getTeaFail];
}
}
@end
//初始化一个领导对象
Leader * leader = [[Leader alloc] init];
//初始化一个职工类对象,将代理传进去
Worker *xiaoli = [[Worker alloc] initWithDelegate:leader];
//模拟去得到茶
[xiaoli goToGetTea];
刚开始的运行结果为
弄茶中...
5秒钟后,运行结果为
弄茶中...
不错不错,这月给你涨工资