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, 这点性能真的没必要。