关于IOS中的delegate必须知道的事情
当你开始写iOS程式不久,应该开始面对到很多的delegate,
不管是用别人的library或是自己写library,可能都逃不了delegate。
为了怕有些人不知道什么是delegate,在这边简单的介绍一下,
delegate中文叫做委托,通常会用在class内部把一些事件处理"委托"给别人去完成。
举个例子,XML Parser可能他知道怎么parse xml,但是parse到的东西要怎么处理xml parser可能不知道。
所以NSXMLParser就提供了一个NSXMLParserDelegate给client去实作,
当parse到某个element的时候,就callback delegate所定义的message,
让他client自己去决定怎么去处理这个element。
好吧,我承认我解释的很模糊,不过我这篇本来就不是要你搞懂什么是delegate,
而是针对使用或是设计delegate的时候,可能会要注意的事情。
在我们的class中设计delegate的时候,我们通常会有几个注意事项。
假设我的class叫做MyClass,那我们可能会有定义一个MyClassDelegate这个protocol当作我的delegate protocol。
而MyClass中我们可能是这样写。
@protocol MyClassDelegate <NSObject>
- (void) myClassOnSomeEvent:(MyClass*)myClass;
@end
@interface MyClass
{
id<MyClassDelegate> _delegate;
}
@property (nonatomic, assign) delegate;
@end
上面的code我们注意到delegate此property是定义为@property (assign)。
为什么我们不用retain而要用assign呢?
原因就是在于iOS的reference counting的环境中,我们必须解决circular count的问题。
让我们来写写我们平常都怎么用delegate的,下面的code我想大家应该不陌生
- (void)someAction
{
myClass = [MyClass new];
myClass.delegate = self;
....
}
这边很快的就出现circular reference了
假设上面的code是写在一个myViewController的物件当中,
之后一旦myViewController的reference count变成1的时候,
myViewController跟myClass这两个兄弟两只剩下互相retain,那就变成了孤岛,也就因此造成了memory leak!!! 
也因为这样,iOS官方文件才会要建议我们所以的delegate都要用assign property。
也就是所谓"weak reference"的property,他的特色就是虽然会持有对方的reference,但是不会增加retain count。
如此下来,当myViewController的retain count变成0,则会dealloc。
同时在dealloc中,也一并把myClass release,则myClass也跟着被release。
- (void)dealloc
{
[myClass release];
[super dealloc];
}

事情就结束了吗? 还没有唷...
这边还有一个大家常常忘记的重点,那就是上面的dealloc这样写会有潜在危险。
应该要改成这样
- (void)dealloc
{
myClass.delegate = nil;
[myClass release];
[super dealloc];
}
你可能会很纳闷,myClass不是马上就会被release了吗? 干嘛要先把他的delegate设成nil?
那是因为我们假设myClass会马上会被dealloc,但是现实状况这个是不一定的,
有可能里面内部有建个NSURLConnection,或是正在做某件事情而让其他物件也retain myClass。
如果myClass没有马上dealloc,那他的myClass.delegate不就正指向一个不合法的位置了吗? (此种pointer称作dangling pointer)

解决方法是在MyViewController的dealloc中,在release myClass之前,
要先把原本指向自己的delegate改设成nil,这样才可以避免crash发生。
在我之前写的project,很大一部份的crash都是这样造成的,因为这个问题通常不是每次都发生,
但是发生的时候确很难在重新复制,所以不可不慎啊。

但是很兴奋的是到了iOS5中的Automatic Reference Counting 这个问题可以有所改善。
在ARC中提出了一个新的weak reference的概念来取代原本的assign,
weak reference指到的物件若是已经因retain count归零而dealloc了,则此weak reference也自动设成nil。
而原本旧的这种assign的作法,在ARC中叫做__unsafe_unretained,这只是为了相容iOS4以下的版本。
回顾重点:
如果你是写library给别人用的,记得把你的delegate设成assign property,这样才不会造成circular reference
当你是要始用别人的library,记得在你自己dealloc的时候,把delegate设成nil,以避免crash的事情发生。
References
[1]Communicating with Objects
关于IOS中的delegate必须知道的事情的更多相关文章
- ios中关于delegate(委托)的使用心得
ios中关于delegate(委托)的使用心得 分类: iOS开发2012-05-15 10:54 34793人阅读 评论(9) 收藏 举报 iosuiviewtimerinterfaceprinti ...
- iOS开发——高级篇——iOS中如何选择delegate、通知、KVO(以及三者的区别)
在开发IOS应用的时候,我们会经常遇到一个常见的问题:在不过分耦合的前提下,controllers[B]怎么进行通信.在IOS应用不断的出现三种模式来实现这种通信:1委托delegation2通知 ...
- iOS中如何选择delegate、通知、KVO(以及三者的区别)
转载自:http://blog.csdn.net/dqjyong/article/details/7685933 在开发IOS应用的时候,我们会经常遇到一个常见的问题:在不过分耦合的前提下,contr ...
- 转iOS中delegate、protocol的关系
iOS中delegate.protocol的关系 分类: iOS Development2014-02-12 10:47 277人阅读 评论(0) 收藏 举报 delegateiosprocotolc ...
- 【学习总结】iOS中NSNotification、delegate、KVO三者之间的区别与联系?
在开发ios应用的时候,我们会经常遇到一个常见的问题:在不过分耦合的前提下,controllers间怎么进行通信.在IOS应用不断的出现三种模式来实现这种通信: 1.委托delegation: 2.通 ...
- iOS 中KVC、KVO、NSNotification、delegate 总结及区别-b
1.KVC,即是指 NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性.而不是通过调用Setter.Getter方法访问.KVO 就是基于 KVC 实现的 ...
- iOS中 Proxy和的delegate区别
在ios中使用proxy代理模式,经常容易和delegate委托模式混淆. 委托模式(delegate),是简单的强大的模式,可让一个对象扮演另外对象的行为.委托对象保持到另外对象的引用,并在适当的时 ...
- iOS中NSNotification、delegate、KVO三者之间的区别与联系?
前面分别讲了delegate.notification和KVO的实现原理,以及实际使用步骤,我们心中不禁有个疑问,他们的功能比较类似,那么在实际的编程中,如何选择这些方式呢? 在网上看到一个博客上详细 ...
- iOS中支付宝集成
iOS中支付宝集成 如今各种的App中都使用了三方支付的功能,现在将我在使用支付宝支付集成过程的心得分享一下,希望对大家都能有所帮助 要集成一个支付宝支付过程的环境,大致需要: 1>公司:先与支 ...
随机推荐
- HTTP协议状态码的含义
HTTP协议状态码的含义 号码含义-----------------------------------------"100":Continue"101":wi ...
- [Wordpress]wp_dropdown_categories() 添加自定义的attribute(属性)
通过Wordpress wp_dropdown_categories()可以获取到Wordpress中的分类列表,假如需要添加一些Html5属性,如required,在看了这个方法的文档说明,没有参数 ...
- @font-face 用字体画图标
HTML <body> <!-- ul.layout>li*5>a[href=#]>i.icon --> <!-- Sublime Text 快捷拼写 ...
- asp.net中用正则表达式验证数据格式
这是一个验证是否为数字的例子: Regex reg = new Regex(@"^[0-9]+\.{0,1}[0-9]*$");reg.IsMatch(textBox1.T ...
- SQL 把查出来的信息整合为一张表
select name ,population from bbc where name='France' union all select name ,population from bbc wher ...
- MVC5 属性路由
属性路由(attribute routing)是最新被引进到MVC5中的,它和传统路由共同组成了mvc5中的两种主要路由. 1. 高质量的url应该满足以下几点 域名便于记忆和拼写 简短 便于输入 可 ...
- UI5_HomeWork
// // View.h // UI5_HomeWork // // Created by zhangxueming on 15/7/2. // Copyright (c) 2015年 zhangxu ...
- Webservice发布出现 测试窗体只能用于来自本地计算机的请求
今天发布了一个接口,一开始以为是.netframework版本的问题,从3.5降到2.0到服务器发布,发布后还是会出现 测试窗体只能用于来自本地计算机的请求 上网查找资料发现原来是 webconfig ...
- 重新审视事件对象event
前言:之前在学习事件对象event时,一是一直在chrome浏览器(作为主运行环境)下运行调试自个儿程序,二是可能当时对事件对象理解不透彻才导致现在对事件对象的用法陷入了一个大坑,遂以此篇博客记之. ...
- javascript笔记——jquery.each中使用continue和break的方式
jQuery.each中continue的方式是 return true break 的方式是return false