- 浏览: 82693 次
- 性别:
- 来自: 天津
文章分类
- 全部博客 (110)
- java (110)
- Comparing PHP Frameworks ( Symfony (1)
- CakePHP (1)
- YII and CodeIgniter) (1)
- spring定时任务的实现 (1)
- 获得一个节点对象的节点类型 (1)
- SWT 文本框Text通过GC重绘改变边框颜色 (1)
- 常用命令收集(系统设置) (1)
- openlayers 应用Google图层你必须做的 (1)
- Shell Sort in Java (1)
- Java网络编程 (1)
- 删除more里面的Edit (1)
- Android颜色选择器 (1)
- Linux安全配置步骤简述 (1)
- 职场官话 (1)
- TOMCAT常用优化 (1)
- 2008 ==> 2009 (1)
- 01_Android介绍 (1)
- HTML特殊字符 (1)
- 终于完成一个最重要的任务——找工作 (1)
- java 加密算法 base64 (1)
- 《南方周末》《南方日报》《新京报》《南方体育》等报纸在线阅读 (1)
- 由ORM框架设计看到微软与苹果的最大差别 (1)
- 通过发微博控制电脑的程序源码 (1)
- flex入门 (1)
- JS合并单元格、JavaScript单元格合并 (1)
- 各种常用编译开关位置 (1)
- 单一入口应用程序概述 (1)
- [转]Cocoa中回调delegate的方法时判断delegate是否已经被释放 (1)
- java简单的通用ajax分页方法 (1)
- /dev/shm放/tmp (1)
- Java中HashMap排序和遍历 . (1)
- Chrome+SwitchySharp+myentunnel+SSH (1)
- LINUX-网卡Bond (1)
最新评论
-
ken890202:
java简单的通用ajax分页方法 -
hanmiao:
真够乱的,什么都看不清。
Linux安全配置步骤简述 -
houxinyou:
说一下我自己的想法.苹果只是做一款相同的东西,然后是完善.有什 ...
由ORM框架设计看到微软与苹果的最大差别 -
delphixp:
微软技术方案很多?。。。。Java 系统笑而不语。。。
由ORM框架设计看到微软与苹果的最大差别 -
huchiwei:
同意楼上说法。这代码....怎么看!!
web应用dao层的开发经验小结
[转]Cocoa中回调delegate的方法时判断delegate是否已经被释放
<p>http://pingguohe.net/2011/09/01/howtojudgewhetheradelegateisreleased/#comment-983</p>
<p>困惑了相当长时间的一个问题了,实际上在Xcode4中会出现?</p>
<p>if ((int)delegate->isa == classIsa) {?</p>
<p>这行报错,member reference base type 'id<HTTPRequestDelegate>' is not a structure or union</p>
<p>因为ide不认为它是NSObject对象,只要对它转为NSObject对象即可。</p>
<p>//************************************************************************************</p>
<p><span style="color: #333333; font-family: 'Trebuchet MS', Helvetica, Arial, Geneva, sans-serif; font-size: 22px; line-height: 26px;">Cocoa中回调delegate的方法时判断delegate是否已经被释放</span><span style="color: #333333; font-family: 'Lucida Grande', Verdana, Helvetica, Arial, Geneva, sans-serif; font-size: 13px; line-height: 20px;">
</span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">这个需要是因为最近在做网络请求的底层,需要在请求完成时回调某delegate的某方法。<br style="padding: 0px; margin: 0px;">然而回调时经常遇到这种情况:delegate已经被release了。如果delegate已经被dealloc掉,则无法调用其方法,否则引起程序crash。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">此篇文章中博客作者也有相同的问题:<a style="color: #5371c5; text-decoration: none; padding: 0px; margin: 0px;" href="http://longtimenoc.com/archives/objective-c-delegate%E7%9A%84%E9%82%A3%E7%82%B9%E4%BA%8B%E5%84%BF">http://longtimenoc.com/archives/objective-c-delegate的那些事儿</a></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">首先,我们此时无法用if (nil = delegate)判断delegate是否已经被dealloc掉,因为被dealloc之后,delegate对象也不是空的,大部分情况下是一个objc_object*类型的C指针。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">其次,我们又会想到在本对象中先对delegate retain一次,这样回调时不会崩溃了。但是这样会出现一个retain cycle,本对象和delegate都永远不会被释放了。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">再次,我想到是否可以用isKindOfClass判断是否被dealloc。然而此时也不能用[delegate isKindOfClass]判断是否已经被dealloc,因为isKindOfClass是NSObject协议中的方法,此时delegate如果不是NSObject,对其发送isKindOfClass消息会导致crash。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">此时很小部分情况下,delegate会是NSObject,可能是NSDictioary,也可能是原本的类。而大部分情况下,delegate已经不是NSObject。所以此时任何形式的[delegate method]都会导致crash,因为任何的[delegate method]的前提都是:delegate是一个NSObject。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">无奈之下我又想到,使用delegate->isa判断delegate是不是NSObject。这里介绍一下,objective-c中所有对象都是结构体,每个结构体中都有一个名为isa的指针指向其类。而类也是一种结构体,类的isa指向其父类。处于最底层的结构体是无isa的,NSObject的isa指向的也是NSObject。isa具体的值是运行时确定的。<br style="padding: 0px; margin: 0px;">一开始的思路是用delegate->isa->isa->isa->…一直指下去,如果isa与NSObject的isa相同,则说明delegate是一个NSObject。但是这样是行不通的,因为如果delegate不是NSObject,只是objc_object*,一直指下去却指不到NSObject的话,总会指到最底层的结构体,而此结构体无isa,如果访问结构体内没有的东西,程序又会crash了。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">说了这么多,结论就是这个问题很是蛋疼。再做不出来我就要把释放本对象的责任交给用户了。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">等等,如果在本对象初始化后,delegate传进来时保存delegate的isa,此时delegate一定未被dealloc(为什么?因为是单线程的),在回调时判断delegate此时的isa和当时保存的isa是否一样,就可以解决了。<br style="padding: 0px; margin: 0px;">代码如下:<br style="padding: 0px; margin: 0px;">协议声明:</p>
<div class="wp_syntax" style="margin-top: 0px; margin-right: 0px; margin-bottom: 1.5em; margin-left: 0px; color: #110000; background-color: #f9f9f9; width: 670px; padding: 0px; border: 1px solid silver;">
<div class="code" style="padding-top: 2px; padding-right: 4px; padding-bottom: 2px; padding-left: 4px; vertical-align: top; margin: 0px;">
<pre class="c">@protocol HTTPRequestDelegate <span style="color: #339933; padding: 0px; margin: 0px;"><</span>NSObject<span style="color: #339933; padding: 0px; margin: 0px;">></span>
?
@optional
?
<span style="color: #339933; padding: 0px; margin: 0px;">-</span> <span style="color: #009900; padding: 0px; margin: 0px;">(</span><span style="color: #993333; padding: 0px; margin: 0px;">void</span><span style="color: #009900; padding: 0px; margin: 0px;">)</span> requestDidLoadResponse<span style="color: #339933; padding: 0px; margin: 0px;">:</span><span style="color: #009900; padding: 0px; margin: 0px;">(</span>NSString <span style="color: #339933; padding: 0px; margin: 0px;">*</span><span style="color: #009900; padding: 0px; margin: 0px;">)</span>responseDictionary<span style="color: #339933; padding: 0px; margin: 0px;">;</span>
<span style="color: #339933; padding: 0px; margin: 0px;">-</span> <span style="color: #009900; padding: 0px; margin: 0px;">(</span><span style="color: #993333; padding: 0px; margin: 0px;">void</span><span style="color: #009900; padding: 0px; margin: 0px;">)</span> requestDidFailedLoadResourceURLWithError<span style="color: #339933; padding: 0px; margin: 0px;">:</span><span style="color: #009900; padding: 0px; margin: 0px;">(</span>NSError <span style="color: #339933; padding: 0px; margin: 0px;">*</span><span style="color: #009900; padding: 0px; margin: 0px;">)</span>error<span style="color: #339933; padding: 0px; margin: 0px;">;</span>
?
@end</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">类声明:</p>
<div class="wp_syntax" style="margin-top: 0px; margin-right: 0px; margin-bottom: 1.5em; margin-left: 0px; color: #110000; background-color: #f9f9f9; width: 670px; padding: 0px; border: 1px solid silver;">
<div class="code" style="padding-top: 2px; padding-right: 4px; padding-bottom: 2px; padding-left: 4px; vertical-align: top; margin: 0px;">
<pre class="c">@interface MyClass <span style="color: #339933; padding: 0px; margin: 0px;">:</span> NSObject <span style="color: #339933; padding: 0px; margin: 0px;"><</span>FooDelegate<span style="color: #339933; padding: 0px; margin: 0px;">,</span>BarDelegate<span style="color: #339933; padding: 0px; margin: 0px;">></span>
<span style="color: #009900; padding: 0px; margin: 0px;">{</span>
...
<span style="color: #993333; padding: 0px; margin: 0px;">int</span> classIsa<span style="color: #339933; padding: 0px; margin: 0px;">;</span>
id <span style="color: #339933; padding: 0px; margin: 0px;"><</span>HTTPRequestDelegate<span style="color: #339933; padding: 0px; margin: 0px;">></span> delegate<span style="color: #339933; padding: 0px; margin: 0px;">;</span>
<span style="color: #009900; padding: 0px; margin: 0px;">}</span>
?
@property <span style="color: #009900; padding: 0px; margin: 0px;">(</span>nonatomic<span style="color: #339933; padding: 0px; margin: 0px;">,</span>assign<span style="color: #009900; padding: 0px; margin: 0px;">)</span> id <span style="color: #339933; padding: 0px; margin: 0px;"><</span>HTTPRequestDelegate<span style="color: #339933; padding: 0px; margin: 0px;">></span> delegate<span style="color: #339933; padding: 0px; margin: 0px;">;</span>
?
@end</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">类实现:</p>
<div class="wp_syntax" style="margin-top: 0px; margin-right: 0px; margin-bottom: 1.5em; margin-left: 0px; color: #110000; background-color: #f9f9f9; width: 670px; padding: 0px; border: 1px solid silver;">
<div class="code" style="padding-top: 2px; padding-right: 4px; padding-bottom: 2px; padding-left: 4px; vertical-align: top; margin: 0px;">
<pre class="c">@implementation MyClass
?
@synthesize delegate<span style="color: #339933; padding: 0px; margin: 0px;">;</span>
?
<span style="color: #339933; padding: 0px; margin: 0px;">-</span> <span style="color: #009900; padding: 0px; margin: 0px;">(</span>id<span style="color: #009900; padding: 0px; margin: 0px;">)</span>initWithDelegate<span style="color: #339933; padding: 0px; margin: 0px;">:</span><span style="color: #009900; padding: 0px; margin: 0px;">(</span>id<span style="color: #009900; padding: 0px; margin: 0px;">)</span>requestDelegate
<span style="color: #009900; padding: 0px; margin: 0px;">{</span>
self <span style="color: #339933; padding: 0px; margin: 0px;">=</span> <span style="color: #009900; padding: 0px; margin: 0px;">[</span>super init<span style="color: #009900; padding: 0px; margin: 0px;">]</span><span style="color: #339933; padding: 0px; margin: 0px;">;</span>
<span style="color: #b1b100; padding: 0px; margin: 0px;">if</span> <span style="color: #009900; padding: 0px; margin: 0px;">(</span>self<span style="color: #009900; padding: 0px; margin: 0px;">)</span> <span style="color: #009900; padding: 0px; margin: 0px;">{</span>
<span style="color: #666666; font-style: italic; padding: 0px; margin: 0px;">//TODO:Send request,etc.</span>
self.<span style="color: #202020; padding: 0px; margin: 0px;">delegate</span> <span style="color: #339933; padding: 0px; margin: 0px;">=</span> requestDelegate<span style="color: #339933; padding: 0px; margin: 0px;">;</span>
<span style="color: #009900; padding: 0px; margin: 0px;">}</span>
<span style="color: #b1b100; padding: 0px; margin: 0px;">return</span> self<span style="color: #339933; padding: 0px; margin: 0px;">;</span>
<span style="color: #009900; padding: 0px; margin: 0px;">}</span>
?
<span style="color: #339933; padding: 0px; margin: 0px;">-</span> <span style="color: #009900; padding: 0px; margin: 0px;">(</span><span style="color: #993333; padding: 0px; margin: 0px;">void</span><span style="color: #009900; padding: 0px; margin: 0px;">)</span>setDelegate<span style="color: #339933; padding: 0px; margin: 0px;">:</span><span style="color: #009900; padding: 0px; margin: 0px;">(</span>id<span style="color: #339933; padding: 0px; margin: 0px;"><</span>HTTPRequestDelegate<span style="color: #339933; padding: 0px; margin: 0px;">></span><span style="color: #009900; padding: 0px; margin: 0px;">)</span>iDelegate
<span style="color: #009900; padding: 0px; margin: 0px;">{</span>
delegate <span style="color: #339933; padding: 0px; margin: 0px;">=</span> iDelegate<span style="color: #339933; padding: 0px; margin: 0px;">;</span>
NSString <span style="color: #339933; padding: 0px; margin: 0px;">*</span>delegateDescription <span style="color: #339933; padding: 0px; margin: 0px;">=</span> <span style="color: #009900; padding: 0px; margin: 0px;">[</span><span style="color: #009900; padding: 0px; margin: 0px;">[</span>iDelegate class<span style="color: #009900; padding: 0px; margin: 0px;">]</span> description<span style="color: #009900; padding: 0px; margin: 0px;">]</span><span style="color: #339933; padding: 0px; margin: 0px;">;</span>
classIsa <span style="color: #339933; padding: 0px; margin: 0px;">=</span> <span style="color: #009900; padding: 0px; margin: 0px;">(</span><span style="color: #993333; padding: 0px; margin: 0px;">int</span><span style="color: #009900; padding: 0px; margin: 0px;">)</span>objc_getClass<span style="color: #009900; padding: 0px; margin: 0px;">(</span><span style="color: #009900; padding: 0px; margin: 0px;">[</span>delegateDescription UTF8String<span style="color: #009900; padding: 0px; margin: 0px;">]</span><span style="color: #009900; padding: 0px; margin: 0px;">)</span><span style="color: #339933; padding: 0px; margin: 0px;">;</span>
<span style="color: #009900; padding: 0px; margin: 0px;">}</span>
?
<span style="color: #339933; padding: 0px; margin: 0px;">-</span> <span style="color: #009900; padding: 0px; margin: 0px;">(</span><span style="color: #993333; padding: 0px; margin: 0px;">void</span><span style="color: #009900; padding: 0px; margin: 0px;">)</span>callback
<span style="color: #009900; padding: 0px; margin: 0px;">{</span>
<span style="color: #b1b100; padding: 0px; margin: 0px;">if</span> <span style="color: #009900; padding: 0px; margin: 0px;">(</span><span style="color: #009900; padding: 0px; margin: 0px;">(</span><span style="color: #993333; padding: 0px; margin: 0px;">int</span><span style="color: #009900; padding: 0px; margin: 0px;">)</span>delegate<span style="color: #339933; padding: 0px; margin: 0px;">-></span>isa <span style="color: #339933; padding: 0px; margin: 0px;">==</span> classIsa<span style="color: #009900; padding: 0px; margin: 0px;">)</span> <span style="color: #009900; padding: 0px; margin: 0px;">{</span>
<span style="color: #b1b100; padding: 0px; margin: 0px;">if</span> <span style="color: #009900; padding: 0px; margin: 0px;">(</span><span style="color: #009900; padding: 0px; margin: 0px;">[</span>delegate respondsToSelector<span style="color: #339933; padding: 0px; margin: 0px;">:</span>@selector<span style="color: #009900; padding: 0px; margin: 0px;">(</span>requestDidLoadResponse<span style="color: #339933; padding: 0px; margin: 0px;">:</span><span style="color: #009900; padding: 0px; margin: 0px;">)</span><span style="color: #009900; padding: 0px; margin: 0px;">]</span><span style="color: #009900; padding: 0px; margin: 0px;">)</span> <span style="color: #009900; padding: 0px; margin: 0px;">{</span>
NSString <span style="color: #339933; padding: 0px; margin: 0px;">*</span>responseString <span style="color: #339933; padding: 0px; margin: 0px;">=</span> @<span style="color: #ff0000; padding: 0px; margin: 0px;">"foobar"</span><span style="color: #339933; padding: 0px; margin: 0px;">;</span>
<span style="color: #009900; padding: 0px; margin: 0px;">[</span>delegate requestDidLoadResponse<span style="color: #339933; padding: 0px; margin: 0px;">:</span>responseString<span style="color: #009900; padding: 0px; margin: 0px;">]</span><span style="color: #339933; padding: 0px; margin: 0px;">;</span>
<span style="color: #009900; padding: 0px; margin: 0px;">}</span>
<span style="color: #009900; padding: 0px; margin: 0px;">}</span>
<span style="color: #009900; padding: 0px; margin: 0px;">}</span></pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">然而由于多线程的原因(发出请求和回调发生是在两个线程上的),会有极少数的情况(测试中发生概率在万分之一以内,和CPU有关)在if ((int)delegate->isa == classIsa)判断时,delegate当前的isa会和本对象初始化时isa相等,也就是说delegate未被dealloc,而调用回调时,delegate已被dealloc,导致程序crash。避免这种小概率事件的方法是,在delegate中发送请求前[self retain]一下,然后在回调到达时[self release]一下,这样除了避免崩溃以外,还会确保请求已经发送完毕,不会被发送一半。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">以上。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px;">–OpenThread</p>
<p>?</p>
发表评论
-
LINUX-网卡Bond
2012-02-08 15:22 844网卡bond是通过把多张网卡绑定为一个逻辑网卡,实现本 ... -
Chrome+SwitchySharp+myentunnel+SSH
2012-02-04 17:14 1848? <p style="margin ... -
Java中HashMap排序和遍历 .
2012-02-03 10:29 1905<div id="article_co ... -
/dev/shm放/tmp
2012-02-02 17:14 878呵呵,有时候不懂装懂的人挺搞笑的哈 转http://z ... -
java简单的通用ajax分页方法
2012-02-02 12:44 1753发表一个自己常用的分页的通用代码,实现了ajax分页。 ... -
单一入口应用程序概述
2012-01-11 14:03 644什么是单一入口应用程序? 在解释什么是单一入口应用 ... -
各种常用编译开关位置
2012-01-11 12:54 649vendor\third-party\products ... -
JS合并单元格、JavaScript单元格合并
2011-12-28 14:08 1058<span style="font-f ... -
flex入门
2011-12-28 12:23 815<span style="fon ... -
通过发微博控制电脑的程序源码
2011-12-20 12:29 1185前段时间看群里挺多讨论 微博api,正好前几天看到有个 ... -
由ORM框架设计看到微软与苹果的最大差别
2011-12-20 09:59 1339一不小心加入水 ... -
《南方周末》《南方日报》《新京报》《南方体育》等报纸在线阅读
2011-12-15 11:04 1216我经常到南方报业提供的网址下载他们出版的报纸看,今天突 ... -
java 加密算法 base64
2011-12-14 17:58 848<span style="color: ... -
终于完成一个最重要的任务——找工作
2011-12-14 14:54 590</span></span>& ... -
HTML特殊字符
2011-12-14 10:54 656最近在做某种模拟器上的网页的显示,需要考虑HTML特殊 ... -
01_Android介绍
2011-12-13 10:44 565? <h4 style="margin ... -
2008 ==> 2009
2011-12-13 10:39 552发现时间过的真的很快,这么快,又是新的一年了。特地翻出 ... -
TOMCAT常用优化
2011-12-12 16:04 634<p class="MsoNorm ... -
职场官话
2011-12-12 12:29 525官场充斥着官话,职场也满是官话,可能你没有注意到而已。 ... -
Linux安全配置步骤简述
2011-12-08 20:04 818<span class="Apple- ...
相关推荐
在Cocoa的开发文档中,Cocoa基本原理指南是介绍Cocoa概念的初级文档,是诸如Cocoa 描画指南和 Cocoa的视编程指南这类文档的先期读物。阅读Cocoa基本原理指南需要的前提条件很少,但读者必须是熟练的 C程序员,且...
详解Cocoa中监听观察和通知五种方法 及其 简介
本人写的一点关于cocoa中使用到的设计模式
Cocoa Fundamentals Guide 的中文版
对于刚刚加入这个阵营的开发者来说,Cocoa 像是一个巨大而未知的新世界。Cocoa 开发环境的各种特性、工具、概念、术语、编程接口、甚至是编程语言对他们来说可能都比较生疏。Cocoa 基本原理指南提供了领略Cocoa 技术...
cocoa常用类及方法 是平时得总结 简单明了
《Cocoa编程开发者手册》共七个部分,详细叙述了核心的框架,以及其他许多用来构建丰富应用程序的组件,指出了庞大的API中最有价值的地方,指引读者进一步学习。 《Cocoa编程开发者手册》适合MacOSX应用程序开发人员...
Cocoa and Objective-C Cocoa and Objective-CCocoa and Objective-C Cocoa and Objective-C
从官网复制的iOS开发参考文献:Cocoa基础指南介绍
cocoa开发者手册是本经典的cocoa开发教程,主要帮助读者理清开发中常用的API,不适合初学cocoa开发的人员
Mantle 是 Cocoa 和 Cocoa Touch 的模型框架,你可以通过它为你的 Cocoa 和 Cocoa Touch 写简单的模型层。示例代码:@interface XYUser : MTLModel @property (readonly, nonatomic, copy) NSString *name;...
cocoa设计模式中文版,给那些中文不好的朋友一点帮助
cocoa avplayer demo xcode中文档的例子
这本书手把手教你使用xcode开发cocoa程序,菜鸟必备
jscocoa, 在Javascript中,编写 Cocoa 应用程序 JSCocoa,从Javascript到 Cocoa的桥梁使用 JSCocoa,可以完全用Javascript编写 Cocoa 应用程序( 几乎),或者将它的用作插件引擎( 比如 和 。) 。 JSCocoa使用 webkit...
Cocoa Design Patterns.pdf Cocoa Design Patterns.pdf
Cocoa入门-使用Objective-C助您轻松体验Cocoa开发,不仅是阅读,还有动手实践。介绍完Xcode和Interface Builder之后,您将很快接触到Objective-C的面向对象编程概念,它是创建Mac OS X应用程序的首选语言。每章中都...
Cocoa下NSTableView的简单使用
cocoa 2d 游戏开发 iphone iOS cocoa2d 游戏 ipad
Mac开发之Cocoa NSTableView中使用CheckBox,Popup,Image