内存的循环引用swift
在 ARC,开发者将会定义一个变量为“strong”或“weak”。一个 weak 弱引用没法 retain 对象,而 strong 引用会 retain 这个对象,并将其引用计数加一。安全
循环引用就是指两个对象互相retain对方,经过OBJC的release是没法销毁这两个对象的app
更严重的是,若是几个对象间接相互引用,好比a<-b b<-c c<-a 那么a、b、c都没法经过release释放工具
循环引用的场景spa
1、定时器NSTimer代理
2、block的使用调试
3、代理delegate对象
4、父子对象关系(swift)内存
定时器:开发
咱们在使用NSTimer时常常会做为一个类的属性使用
而NSTimer在初始化的时候回指定self为target.这就形成了self—>NSTimer-->self的循环引用的状况。另外在NSTimer一致处于validata状态时其引用计数器一直是大于0的
解决办法:在不使用定时器之后要调用invalidata移除定时器。
block的使用
block在引用外部的变量是,会对外部变量进行copy操做。在(ARC)模式下会对变量进行强引用,(MRC)模式下变量retainCount加1。当一个类把block做为成员变量时,在block内部使用了这个类自己。形成self—>block-->self或者self-->block-->类的成员变量循环引用的状况。
解决办法:在MRC模式下,在给block赋值时在外部用__blockmySelf = self;用__block修饰使用到的类。
在ARC模式下,用__weak修饰
代理:
代理协议也是一个典型的场景,须要你使用弱引用来避免循环引用。将代理声明为 weak 是一个即好又安全的作法
父子对象关系
父子对象关系是一个循环引用的典型案例,不幸的是,它也是惟一一个存在于苹果文档中的案例。典型的解决方法就是,在子类定义一个指向父类的变量,声明为 weak 弱引用,从而避免循环引用。
在 swift 中子类指向父对象的变量是一个弱引用,这就迫使咱们将该弱引用定义为 optional 类型。若是不使用 optional 能够有另外一种作法,将指向父对象的变量声明为“无主引用(unowned)”(代表咱们不持有该对象,也不对其进行内存管理)。然而在这种状况下,咱们必须很是当心,确保只要还有子对象指向它,父对象不变成 nil,不然会直接闪退。
调试:
使用 Instruments 调试循环引用
XCode 自带了一个很强大的工具 Instruments,用于检测和定位循环引用。一旦你的 app 开发结束,即将提交到 Apple Store,先分析你的 app 是一个好的习惯。Instruments 有不少组件,能够用来分析 app 的不一样方面,可是咱们如今关心的是 Leak 选项。