闭包中的循环引用可通过weak与unowned解决
weak引用时:必须是可选类型的var,因为实例销毁后,ARC会自动将弱引用设置为nil。此时不会触发属性观察器(willSet/didSet)
unowned引用时: 不会产生强引用,实例销毁后仍然存储着实例的内存地址。如果在实例销毁后继续访问无主引用,会产生运行时错误(野指针)
class Person {
var fn: (() -> ())?
func run() {
print("Person run")
fn?()
}
deinit{
print("Person deinit")
}
}
当另一个页面调用闭包时,以下代码会造成循环引用,不会来到deinit方法
var id = 1
func test() {
p.fn = { () in
print("调用了person fn",self.id)
}
p.run()
}
一、使用weak解决循环引用
写法一
写法二
二、使用unowned解决循环引用
写法一
写法二
如果是lazy属性闭包调用,则不用考虑循环引用的问题,因为调用后,闭包的生命周期就结束了
三、weak与unowned的区别
1、使用weak,在闭包中访问外界变量返回可选类型;而unowned则返回原类型
2、在实例销毁后继续访问(unowned)引用,会产生运行时错误(野指针),如下图所示
unowned var up = Person()
func test() {
up.run()
}