Swift weak 与 unowned
在用 Swift 做开发时,我们可以使用 weak 或是 unowned 打破类实例和闭包的强引用循环。我们来看下 weak 和 unowned 的相同和不同之处。
weak
日常开发中,我们经常会用weak
来标记代理或者在闭包中使用它来避免引用循环。
weak var delegate: SomeDelegate?
lazy var someClosure: () -> Void = { [weak self] in
guard let self = self else { retrun }
self.balabala
}
当我们赋值给一个被标记weak
的变量时,它的引用计数不会被改变。而且当这个弱引用变量所引用的对象被释放时,这个变量将被自动设为nil
。这也是弱引用必须被声明为Optional
的原因。
unowned
和weak
相同,unowned
也可以在不增加引用计数的前提下,引用某个类实例。
unowned let someInstance: SomeClass
lazy var someClosure: () -> Void = { [unowned self] in
self.balabala
}
在使用unowned
时,我们不需要将变量声明为Optional
。
需要注意的是。对于被unowned
标记的变量,即使它的原来引用已经被释放,它仍然会保持对被已经释放了的对象的一个 "无效的" 引用,它不是Optional
,也不会被指向 nil
。所以,当我们试图访问这样的unowned
引用时,程序就会发生错误。
看这个描述是不是有点眼熟,作为 iOS 开发的老司机,这东西像不像OC里的 __unsafe_unretained
__weak
对性能会有一定的消耗,使用__weak
,需要检查对象是否被释放,在追踪是否被释放的时候当然需追踪一些信息,那么此时__unsafe_unretained
比__weak
快,而且一个对象有大量的__weak
引用对象的时候当对象被废弃,那么此时就要遍历weak
表,把表里所有的指针置空,消耗cpu资源。
不过我感觉这东西真的没必要,比起 crash, 这点性能真的没必要。