ios学习笔记——代理设计模式
在ios项目开发中,我们经常会使用代理设计模式,代理设计模式是一种消息传递的方式,可以通过这种方式来传递一些参数。
代理的基本使用
代理设计模式主要由三部分组成:1、协议,2、代理,3、委托。
1、协议:定义接口,用来指定代理和委托可以做什么,必须做什么。OC语言用@protocol来实现。
2、代理:实现协议接口的方法,完成委托需要实现的任务。
3、委托:根据协议定义deleage对象(代理对象,弱引用weak),指定在什么情况下要求代理对象去完成什么功能。
举个不太恰当的例子:代理模式组成的三部分很像项目经理、需求文档、程序员。需求文档相当于协议,项目经理根据需求文档要求程序员去完成任务。项目经理相当于委托,他根据需求文档,要求程序员去完成需求文档中的任务。程序员相当于代理,根据需求文档,完成项目经理分配的任务。
需求文档(协议)
协议只能定义一套接口,但是不能提供具体的实现。方法需要去实现此协议的类里去实现。
协议可以继承其他协议,并可以继承多个,iOS中不支持多继承,而协议可以,所以iOS中的多继承可以使用协议来代替。
协议有两个修饰符@optional和@required。如果没有声明,默认是@required(必须实现)。这两个修饰符只是约定代理是否强制遵守协议,如果是@required状态的方法没有实现,会报一个黄色的警告,只是起一个约束的作用。
协议通过<>进行实现,一个类可以同时实现多个协议,中间用逗号分隔。
协议中不能定义属性、成员变量等,只能定义方法。
定义协议代码:
1 //声明协议,可以扩展协议 2 @protocol requirementsDocumentDeleage <NSObject> 3 4 - (void)completeTask; 5 6 @end
项目经理(委托)
委托类需要显示的声明一个delegate属性,如下
1 //通过属性来实现代理,这里必须用weak,避免引用循环 2 @property (nonatomic, weak) id<requirementsDocumentDeleage> delegate;
这里必须用weak将deleagte声明为弱引用,避免引用循环(不一定造成引用循环,但是这样做比较保险)。
在我们需要deleage做一些事情的时候,我们就需要向delegate发送消息了,代码如下:
1 //判断代理对象存在,是否实现该方法,否则,没有实现会导致崩溃 2 if(self.delegate != nil && [self.delegate respondsToSelector:@selector(completeTask)]){ 3 [self.delegate completeTask]; 4 }
协议一般声明在委托类的头文件中,如果好多委托类使用协议,则应该单独声明在一个头文件中。
代理对象(程序员)
第一步,这个类必须在声明上,或者类扩展中实现协议,用<>,这里可以实现多个协议,用逗号隔开
1 @interface SJZProgrammerViewController () <requirementsDocumentDeleage>
第二步,设置委托类的delegate对象为代理类对象
1 SJZProjectExperienceView * peView = [[SJZProjectExperienceView alloc] initWithFrame:CGRectMake(0, 200, self.view.frame.size.width, 60)]; 2 peView.delegate = self; 3 [self.view addSubview:peView];
第三步,实现协议方法
1 - (void)completeTask 2 { 3 self.label.text = @"完成任务"; 4 }
代理实现流程
在ios中代理的本质就是代理对象内存的传递和操作,我们在委托类设置代理对象之后,实际上就是给id类型的指针将代理对象进行了一个弱引用。委托类让代理类执行操作,实际上是在委托类中像这个id类型指针的对象发送消息,而id类型指针指向了代理对象。
代理设计模式的优缺点
优势:
1、语法严格,代理类中所实现的方法必须在协议中有清晰的定义
2、如果代理类中,协议的必须实现方法没有实现那么就会出现编译警告/错误
3、应用中,deleage的控制流程是可跟踪的并且是可识别的
4、可以在一个委托类中定义多个不同的协议,每个协议有不同的delegate
5、没有第三方对象要求保持/监听通信过程
6、委托能够接收调用的协议方法的返回值,这意味着代理类能够反馈信息给委托类
缺点:
1、需要实现的代码比较多:比如协议、delegate属性、协议方法的实现。
2、在释放对象的时候,需要将delegate改为nil,否则,可能在对象释放的时候出现内存泄漏。
3、当多个相同的委托对象的delegate指针指向同一个代理类,这时每个协议方法只能实现一次,处理逻辑比较复杂,需要判断具体是哪个委托对象要求代理类做任务的。
参考连接:
http://blog.csdn.net/yangxt/article/details/8176636
http://www.cocoachina.com/ios/20160317/15696.html
http://blog.csdn.net/jianxin160/article/details/47753189