Swift: 對於weak、unowned的理解

可參考這些文章:

1.Swift內存管理、weak和unowned以及兩者區別(如何使用Swift 中的weak與unowned?)

2.Swift:Weak 和 Unowned

3.扒一扒swift中的unowned和weak下

 

總結:

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()
//    }
//})()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章