iOS中的强代理(strong delegate)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS中的强代理(strong delegate)相关的知识,希望对你有一定的参考价值。

参考技术A 一般来说, ios中的代理都是weak类型的, 这是因为一般代理者都是代理持有者的父对象, 而父对象会持有代理持有者. 因此, 如果代理是强类型, 则会导致循环引用. 虽说代理者不一定得是代理持有者的父对象, 但是这是最常见的使用场合, 用于子对象向父对象传递数据.

比如一个UIViewController是一个View的delegate, 在View上的某些操作需要传递给UIViewController, 从而UIViewController做出某些响应.

另一种情况, (父对象)并不需要持有代理持有者, 只是需要在某些操作时做出响应, 而这些响应并不需要(父对象)持有代理持有者, 但是需要代理持有者维持一定的什么周期. 比如一些连接网络的操作. 这时就不会出现循环引用的情况.

到底是使用strong delegate还是weak delegate, 归根结底由调用者(父对象)决定, 调用者是否需要持有代理持有者. 但是话说回来, delegate的weak(strong)属性需要在声明时就指定. 要是遇到有时需要strong delegate有时需要weak delegate时怎么办呢? 这时我们就需要用到另一种回调方式block.

在block中, 当可能引起循环引用时, 不直接持有父对象, 即self对象, 而是使用self对象的弱引用,比如使用 __weak typeof(self) weakSelf = self; 然后在block内部用weakSelf代替self.

在iOS中存在一类strong类型的delegate, 比如CoreAnimation的代理和NSURLSession的代理. 使用强代理是因为动画和网络请求在异步执行, 而异步执行中随时可能会丢失销毁对象, 当执行完成之后再手动销毁对象. 因此要使用strong delegate, 必须当任务完完成时在将delegate=nil来释放delegate.

由于笔者知识有限,如有错误,欢迎讨论指出。

iOS 代理(Delegate)

一、代理的特点

  • 准确的说是一种软件设计模式
  • iOS当中以@protocol形式提现
  • 传递方式一对一

二、代理的基本使用

代理是一种通用的设计模式,在iOS中有特定的语法来实现代理模式,OC语言可以通过@Protocol实现协议。

1、代理组成部分

  • 协议:用来指定代理双方可以做什么,必须做什么。
  • 代理:根据协议,完成委托方需要实现的功能(方法)。
  • 委托:根据协议,指定代理去完成什么功能。

2、协议(Protocol)的概念


从上图中我们可以看到三方之间的关系,在实际应用中通过协议来规定代理双方的行为,协议中的内容通常情况都是方法列表,当然也可以定义属性.(后面会介绍协议属性)协议是公共的,如果只是单单某个类去使用,我们常做的就是写在某个类中。如果多个类都是使用同一个协议,这里建议大家创建一个Protocol文件,在这个文件中制定协议。遵循的协议可以被继承!

  • 协议只能定义公用的一套接口,类似于一个约束代理双方的作用。但不能提供具体的实现方法,实现方法需要代理对象(可以理解为接受协议遵守协议的代理人)去实现。
  • 协议可以继承其他协议,也可以继承多个协议,在iOS中对象是不支持多继承的,而协议是可以多继承。
  • 协议有两个修饰符@optional和@required,创建一个协议如果没有声明修饰符,默认是@required状态的。这两个修饰符只是约定代理是否强制需要遵守协议,如果@required状态的方法代理没有遵守,Xcode会报一个黄色的警告,@required是需要我们必须实现的。@optional是可以选择实现的.

3、代理原理

我们发现,其实委托方的代理属性本质上就是代理对象自身,设置委托代理就是代理属性指针指向代理对象,相当于代理对象只是在委托方中调用自己的方法,如果方法没有实现就会导致崩溃。从崩溃的信息上来看,就可以看出来是代理方没有实现协议中的方法导致的崩溃。
而协议只是一种语法,是声明委托方中的代理属性可以调用协议中声明的方法,而协议中方法的实现还是由代理方完成,而协议方和委托方都不知道代理方有没有完成,也不需要知道怎么完成。

4、内存管理


我们定义的指针默认都是__strong类型的,而属性本质上也是一个成员变量和set、get方法构成的,strong类型的指针会造成强引用,会造成循环引用。
由于代理方使用强引用指针,引用创建的委托方,并且成为委托方的代理。这就会导致委托方的delegate属性强引用代理方,导致循环引用的问题,最终两个对象都无法正常释放。

三、代理和block对比

  • 在有多个消息传递时,用delegate实现更合适,看起来清晰;
  • 代理更加面相过程,block则更加面相结果。
  • 从设计模式的角度来说,dialing更加面相过程,而block更加面相结果。
  • 从性能上来说,block的性能消耗要更略大于delegate,以为block会涉及到栈区向堆区拷贝等操作,时间和空间上的消耗都大于代理。而代理只是定义了一个方法列表,在遵守协议对象的objc_protocol_list中添加一个节点,在运行时向遵守协议的对象发送消息即可。

以上是关于iOS中的强代理(strong delegate)的主要内容,如果未能解决你的问题,请参考以下文章

iOS 关于修饰代理用weak还是assign

22iOS面试题·自整理·Four

iOS内存管理-- iOS 代理要用weak修饰

【iOS】协议(Protocol)和代理(Delegate)

java中的强引用(Strong reference),软引用(SoftReference),弱引用(WeakReference),虚引用(PhantomReference)

IOS 代理模式 DELEGATE