Swift 内存管理ARC 以及循环引用思考


内存管理是编程时一个不可回避的问题,在Swift中,是自动管理内存的,也就是ARC机制,自动引用计数机制。我们不需要关心内存的申请和分配。

ARC工作机制

当我们每次创建一个类的新实例的时候,ARC会为我们分配一块内存来存储实例的信息。当该实例不在被使用时即一个实例没有引用的时候,ARC会为我们释放掉所占用的内存,也就是即使清除内存,不造成内存泄露。

如果我们正在使用的实例被ARC回收掉。当我们在此访问的时候会造成崩溃。为了保证真正使用的实例内存不会被回收,ARC会跟踪和计算每一个实例被引用的数量,如果不为0,就不会销毁或回收。

如果想要我们的实例不会被销毁,我们需要创建该类实例的强引用。

循环引用

当两个对象相互强引用对方的时候,其中都不能被释放,就出现了循环引用

class Person:NSObject{
    var name:String
    init(name:String) {
        print("\(name) 被初始化")
        self.name = name
    }
    var car:Car? = nil
    deinit {
        print("\(name) 被释放")
    }
}

class Car:NSObject{
    var id:String
    init(id:String) {
        print("\(id) 被初始化")
        self.id = id
    }
    var person:Person? = nil
    deinit {
        print("\(id) 被释放")
    }
}

        var james:Person? = Person(name: "James")
        var bmw:Car? = Car(id: "湘B:88888")
        james!.car = bmw
        bmw!.person = james
        // James 被初始化
        // 湘B:88888 被初始化
        james = nil
        bmw = nil
        // 并未打印 James 被释放
        // 湘B:88888 被释放

上述代码中就出现了循环引用,查找原因。两个对象相互强引用对方,导致谁都无法释放。也就james中间引用了bmw,而bmw中也引用了james,当我们尝试去释放james的时候,由于james的成员变量bmw无法被释放,导致自身也无法被释放。

weak、unowned解决循环引用问题

weak var car:Car? = nil
weak var person:Person? = nil

我们在两个类的成员变量前面加上 weak 关键字,很顺利的得到了我们想要的结果,两个实例被释放。

james = nil
bmw = nil
//  James 被释放
// 湘B:88888 被释放

weak: 当一个对象被声明为weak时,表示父层级对改对象没有指向,该对象的ARC 引用计数不会+1。当对象被释放后,弱引用也随即消失。继续访问改对象,程序会得到nil,不会引起崩溃。
unowned: 它与weak的本质是一样的,不同点在于,对象被释放后,依然有一个无效的指向引用,它不是可选,也不是nil,继续访问改对象,会引起奔溃


文章作者: Cone
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 Cone !
  目录