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