可参考这些文章:
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()
// }
//})()