转自:http://longtimenoc.com/archives/objective-c-delegate的那点事儿
事情源于,网络请求中(未返回数据)退回到上一级,网络请求结束后,程序crash掉了,
if (delegate && [delegate respondsToSelector:didFailSelector]) {
EXC_BAD_ACCESS
----------------------------------------
Delegate算是Objective-C的一大特性, 关于Delegate的基础就不多介绍了, 有兴趣的请参看文档.
这里仅对Delegate使用中的一些问题做点讨论
我们用Delegate很多情况下是基于多线程的,比如我们有一个ViewController在这个Controller里面进行了一个下载图片的操作,下载成功后需要通过protocol来现实下载成功, 但是当ViewController已经被release,而下载工作才结束, 那么下载工作的[delegate didFinishDownload] (暂且就这么命名吧) 就会产生一个异常,因为你给一个deallocated的对象发送了一个消息.
那么,如何解决这个问题呢,首先我们可能想到用if (delegate == nil) 来判断delegate是否存在,但其实这是不行的,因为已经dealloc的对象并不是nil.要知道Objective-C中给nil发送消息是可以的,所以如果这种方法可行,其实我们就根本不需要if这句,[delegate didFinishDownload] 给nil发送了一个消息也不会出现异常,因此这种方法只是重复了上面的错误.
还有一个叫[delegate respondsToSelector:SEL]来判断delegate是否响应一个Selector, 根据上一段的描述,我们也可以判断出这个也是不行的.这里额外提一点关于respondsToSelector的东西,要使用这个方法,必须有@protocol MyProtocol <NSObject>,因为respondsToSelector是NSObject的一个protocol方法.
既然要防止delegate被release,那么retain这个delegate是否可行呢?这么做虽然避免错误的发生,但是也产生了另一个问题,这就关系到Objective-C内存管理中的Retain Circle, 即:有A,B两个Object, A中有一个B的实例变量,B中又有一个A的实例变量,要release A就必须releaseA中的B,而要release B有必须release B中的A,这样就产生了一个Retain Circle,A B都不能被dealloc.解决Retain Circle的方法就是使用弱引用(weak reference),弱引用没有被引用的那个Object的所有权,也就不需要release它,从而解决了Retain Circle问题.为了防止Retain Circle的发生, delegate通常都是弱引用的, 因此我们一般不应该retain一个delegate.但是似乎有一个例外:NSURLConnection, 网上对其的讨论结果是:NSURLConnection会retain它的delegate,详细可以参考StackOverflow上的这个问题
似乎没有简单可行的方法来解决这个问题(至少在本文发表时我还没有找到),那么我们只能在通过程序结构的设计来解决这一问题了,对应不同的程序自然也就有不同的解决方法,我想到的一种就是在这个ViewConrtoller被release的时候,把下载方法中的delegate设置成nil即可(目前测试可行, 如有错误还请指正).
分享到:
相关推荐
1. **Objective-C基础**:Objective-C是在C语言基础上扩展的,添加了面向对象特性。它的基础包括类、对象、消息传递等概念。类定义了对象的属性和行为,对象则是类的实例。消息传递是Objective-C的核心,通过`...
Objective-C的委托(Delegate)机制是面向对象编程中一种重要的设计模式,它允许一个对象(委托方)将某些任务或事件处理权交由另一个对象(被委托方)来执行。在Objective-C中,委托通常用于实现组件之间的通信,如...
Objective-C中的委托(Delegate)是实现对象间通信的一种重要机制,它允许一个对象与另一个对象进行交互,而无需显式地持有对方的引用。在iOS和macOS开发中,委托模式广泛应用于各种场景,如视图控制器间的通信、...
1. **Objective-C的起源与特性**:Objective-C是在C语言的基础上扩展的,增加了消息传递机制和面向对象特性。它的语法包含C语言的所有部分,同时引入了类、继承、多态等OOP概念。 2. **类与对象**:在Objective-C中...
Objective-C是在C语言的基础上扩展了Smalltalk式的面向对象特性,使得它既有C语言的强大功能,又具备了面向对象编程的灵活性。 在Objective-C中,类是所有对象的基础。类定义了一组属性(实例变量)和方法(函数)...
1. **Objective-C基础**:Objective-C是C语言的超集,它引入了Smalltalk的类、消息传递等面向对象特性。了解基本的数据类型、变量声明、控制流语句(如if、for、while)以及函数定义是开始的基础。 2. **类和对象**...
1. 类与对象:Objective-C中的所有操作都基于类和对象。为了实现汉诺塔,我们需要定义一个`Tower`类来表示柱子,它包含盘子数组和方法来添加、移除盘子。同时,还需要一个`Disk`类来表示盘子,包含盘子大小等属性。 ...
Objective-C的起源可以追溯到C语言,它扩展了C的语法,加入了Smalltalk的面向对象特性。在Objective-C中,类是对象的蓝图,对象则是程序中的基本工作单元。理解类和对象的概念是学习Objective-C的第一步。 首先,你...
### Objective-C语言教程、案例与项目资源详解 #### 一、Objective-C基础知识 **1.1 类与对象** Objective-C的核心概念是类和对象。类是对象的模板或蓝图,它定义了对象应该具备哪些属性(如变量)和行为(如方法...
SAF-Object-Delegate 基于 Kotlin 的委托机制实现对 Extra、SharedPreferences 的封装 模块 extras-delegate prefs-delegate prefs-fastjson-delegate prefs-gson-delegate 最新版本 一. 封装...
Objective-C是一种强大的面向对象的编程语言,主要用于Apple的iOS和macOS平台开发。它是由Stepanov和Moss在C语言的基础上添加了Smalltalk的面向对象特性而创建的。本资料"Objective-C高级编程"旨在帮助已经入门的iOS...
Objective-C作为C语言的一种超集,保留了C语言的所有特性,并在其基础上增加了面向对象的特性。这意味着开发者可以在Objective-C中使用C语言的所有语法和功能,同时也能享受面向对象带来的便利。Objective-C的一个...
Objective-C是由C语言发展而来,融入了Smalltalk的面向对象特性,因此它结合了C的简洁性和面向对象的灵活性。 1. **面向对象编程基础**: Objective-C的核心是它的面向对象特性,包括类(Class)、对象(Object)...
Objective-C是一种面向对象的编程语言,由Smalltalk和C语言发展而来。它在20世纪80年代初被设计出来,并在苹果公司开发iOS和macOS应用程序时得到了广泛应用。Objective-C的主要特点在于其动态特性、消息传递机制以及...
1. **消息传递**:Objective-C的核心特性是消息传递机制。对象通过发送消息来调用方法,这与传统的函数调用不同。例如,`[anObject performSelector:@selector(aMethod)]` 就是在向`anObject`发送一个消息,让它执行...
在iOS开发中,Objective-C是主要的编程语言之一,用于构建原生的移动应用程序。`NSURLSession`是苹果提供的一个强大的网络编程接口,用于处理HTTP和其他网络协议的数据传输。本示例将详细介绍如何使用Objective-C和...
技术关键词:Objective-C、iOS开发、Mac OS X、编程语言、面向对象编程、内存管理、自动引用计数(ARC)、协议(protocol)、类扩展(category)、键值观察(KVO)、键值编码(KVC)、Block、Delegate模式、多态性、...
Objective-C 是基于C语言的,它添加了消息传递机制、类和协议等面向对象的特性。消息传递是Objective-C中的核心概念,通过`[receiver message]`的形式进行调用。类定义了对象的结构和行为,而协议则允许实现接口...