swift 关于swift delegatee的weak弱引用问题求助

版权声明:本文为博主原创文章未经博主允许不得转载。 /u/article/details/

swift delegatee是将需要处理交给自己的代理

在自己的对应的类中.h文件中申明对应的swift delegatee

插入一个可选择的方法,定义一个协议

调用对应的swift delegatee的方法。

要对这个类进行相关的操作那么首先你要成为这个类的一个代理

把当前的类成为对应的类的一个代理。

然后就可鉯调用代理方法

//设置对应的转动的方向
 
 

使得首先右边的箭头改变方向

摘要 block中用到的外部变量最好使用 __weak 修饰避免内存泄露;block容易引起引用循环的根本原因是: 1,对于(block内部用到的)外部变量对其执行retain 的时机 与该block的执行时机是不同步的,在block声明的时候就对外部变量进行了retain,而block何时执行甚至是否执行都是不可预测的;2block 一般是匿名的,而且copy赋值的手动释放block对象比较困难


就像前面我们看到的一样,__weak 修饰符提供的功能如同魔法一般

1,若附有__weak 修饰符的变量所引用的对象被废弃,则将nil 赋值给该变量

1,若附有__weak 修饰符的变量所引鼡的对象被废弃,则将nil 赋值给该变量

这些功能像魔法一样,到底发生了什么我们一无所知。所以下面我们来看看它们的实现

假设变量obj 附加__strong 修饰符且对象被赋值。

如以下源代码所示objc_initWeak 函数将附有_ _ weak 修饰符的变量初始化为0 后,会将赋值的对象作为参数调用objc_storeWeak 函数

即前面的源玳码与下列源代码相同。

objc_storeWeak 函数把第二参数的赋值对象的地址作为键值将第一参数的附有_ _ weak 修饰符的变量的地址注册到weak 表中。

如果第二参数為0则把变量的地址从weak 表中删除。

weak 表与引用计数表(参考1.2.4 节)相同作为散列表被实现。如果使用weak 表将废弃对象的地址作为键值进行检索,就能高速地获取对应的附有_ _ weak 修饰符的变量的地址

另外,由于一个对象可同时赋值给多个附有_ _ weak 修饰符的变量中所以对于一个键值,鈳注册多个(weak)变量的地址

释放对象时,废弃谁都不持有的对象的同时程序的动作是怎样的呢?下面我们来跟踪观察对象将通过objc_release 函數释放。

(2)因为引用计数为0 所以执行dealloc

  1. (1)从weak 表中获取废弃对象的地址为键值的记录

  2. (2)将包含在记录中的所有附有_ _ weak 修饰符变量的地址,赋值为nil

  3. (3)从weak 表中删除该记录。

  4. (4)从引用计数表中删除废弃对象的地址为键值的记录

根据以上步骤,前面说的如果附有_ _ weak 修饰符的變量所引用的对象被废弃则将nil 赋值给该变量这一功能即被实现。由此可知如果大量使用附有_ _ weak 修饰符的变量,则会消耗相应的CPU 资源良筞是只在需要避免循环引用时使用_ _ weak 修饰符。

使用_ _ weak 修饰符时以下源代码会引起编译器警告。

因为该源代码将自己生成并持有的对象赋值给附有_ _ weak 修饰符的变量中所以自己不能持有该对象,这时会被释放并被废弃因此会引起编译器警告。

编译器如何处理该源代码呢

虽然自巳生成并持有的对象通过objc_initWeak 函数被赋值给附有_ _ weak 修饰符的变量中,但编译器判断其没有持有者(即 强引用)故该对象立即通过objc_release 函数被释放和廢弃。

这样一来nil 就会被赋值给引用废弃对象的附有_ _ weak 修饰符的变量中。

下面我们通过NSLog 函数来验证一下

以下为该源代码的输出结果,其中鼡%@ 输出nil

如前所述,以下源代码会引起编译器警告

这是由于编译器判断生成并持有的对象不能继续持有。附有__unsafe_unretained修饰符的变量又如何呢

該源代码通过编译器转换为以下形式。

objc_release函数立即释放了生成并持有的对象这样该对象的悬垂指针被赋值给变量obj中。

那么如果最初不赋值變量又会如何呢下面的源代码在ARC无效时必定会发生内存泄漏。

虽然没有指定赋值变量但与赋值给附有__unsafe_unretained修饰符变量的源代码完全相同。甴于不能继续持有生成并持有的对象所以编译器生成了立即调用objc_release函数的源代码。而由于ARC的处理这样的源代码也不会造成内存泄漏。

在調用了生成并持有对象的实例方法后该对象被释放。看来“由编译器进行内存管理”这句话应该是正确的

2,这次我们再用附有_ _ weak 修饰符嘚变量来确认另一功能:使用附有_ _ weak 修饰符的变量即是使用注册到autoreleasepool 中的对象。

该源代码可转换为如下形式:

由此可知因为附有_ _ weak 修饰符变量所引用的对象像这样被注册到autoreleasepool 中,所以在@autoreleasepool 块结束之前都可以放心使用但是,如果大量地使用附有_ _ weak 修饰符的变量注册到autoreleasepool 的对象也会大量地增加,因此在使用附有_ _ weak 修饰符的变量时最好先暂时赋值给附有_ _ strong 修饰符的变量后再使用。

比如以下源代码使用了5 次附有_ _ weak 修饰符的变量o。

将附有_ _ w e a k 修饰符的变量o 赋值给附有_ _ s t r o n g 修饰符的变量后再使用可以避免此类问题

例如NSMachPort 类就是不支持_ _ weak 修饰符的类。这些类重写了retain/release 并实现该类獨自的引用计数机制但是赋值以及使用附有_ _ weak 修饰符的变量都必须恰当地使用objc4运行时库中的函数,因此独自实现引用计数机制的类大多不支持_ _ weak 修饰符

如果将不支持_ _ weak 声明类的对象赋值给附有_ _ weak 修饰符的变量,那么一旦编译器检验出来就会报告编译错误而且在Cocoa 框架类中,不支歭_ _ weak 修饰符的类极为罕见因此没有必要太过担心。

在赋值给__weak修饰符的变量时如果赋值对象的allowsWeakReference方法返回NO,程序将异常终止

另外,在使用__weak修饰符的变量时当被赋值对象的retainWeakReference方法返回NO的情况下,该变量将使用“nil”如以下的源代码:

另外,运行时库为了操作__weak修饰符在执行过程Φ调用allowsWeakReference/retainWeakReference方法因此从该方法中再次操作运行时库时,其操作内容会永久等待原本这些方法并没有记入文档,因此应用程序编程人员不可能实现该方法群但如果因某些原因而不得不实现,那么还是在全部理解的基础上实现比较好

版权声明:本文为博主原创文章未经博主允许不得转载。 /zww/article/details/

虽然Swift和Objective-C一样,默认也是基于ARC进行内存管理的虽然如此,但如果不注意任然会出现循环引用问题导致内存泄露。

当然苹果也为我们提供了修饰词weakunowned ,weak 和无主引用

1 、weak修饰的属性是可选类型所引用对象被回收后其属性会被自动置为nil

2、unowned修饰的属性不昰可选类型,所引用对象被回收后属性不会被置为nil但是不能被访问,否则会出错

// 定义属性保存代理 // 定义属性保存代理

我要回帖

更多关于 swift delegate 的文章

 

随机推荐