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

  

posted @ 2017-06-15 16:05  雪佛兰,热爱我的热爱  阅读(1352)  评论(0编辑  收藏  举报