Swift: 对于weak、unowned的理解
可参考这些文章:
1.Swift内存管理、weak和unowned以及两者区别(如何使用Swift 中的weak与unowned?)
总结:
1.共同点:
1.1 引用对象的自动引用计数都不会加1,不会造成对引用对象的强引用。
2.不同点:
2.1 weak的对象,在block块内再次获取值时可能为nil,相当于变成了一个可选值,调用属性或者方法需要加上?或者强制解析!,但是强制解析在对象已经被释放了时肯定会造成强解错误,导致程序崩溃。
2.2 unowned的对象,在block块内再次获取值时依然是对象本身,只是该对象可能被释放了,因此调用者必须保证在执行block块时该对象一定依然存在,不然调用对象的方法时会造成崩溃。
3. 另外,你还可以利用【生命周期】的长短去理解,即分别在什么场景下使用unowned和weak:
3.1 unowned所在的block的生命周期务必要比unowned修饰对象的生命周期短,即block一旦销毁了,也就不会再调用了,也就不存在修饰对象的引用问题了。
3.2 weak所在的block可能要比weak修饰对象的生命周期长,block被调用时,修饰对象可能已经释放掉了,此时通过修饰对象?去调用也就不会引发问题,保证程序正常运行。
你可以在playground中编写代码试验一下,这样能加深理解。
下面是我的测试代码。
class A: NSObject { let b: B override init() { b = B() super.init() b.a = self } func methodA() { print("A methodA") } deinit { print("A deinit") } } class B { weak var a: A? = nil func methodB() { print("B methodB") } deinit { print("B deinit") } } class E { func execute(block: (() -> Void)?) { print("E: executing...") block?() } } // ======== 1 ======== //var a: A? = A() //a = nil // ======== 2 ======== //({ // let a = A() //})() ({ // ======== 3 ======== let _a0: A = A() E().execute { [unowned _a0] in _a0.b.methodB() } // ======== 4 ======== let _a1: A? = A() E().execute { [weak _a1] in _a1?.b.methodB() } })()