Swift-循环引用(弱引用(weak reference)和无主引用(unowned reference))

Swift 使用自动引用计数(ARC)机制来跟踪和管理你的应用程序的内存。ARC 会在类的实例不再被使用时,自动释放其占用的内存。如果两个类实例互相持有对方的强引用,因而每个实例都让对方一直存在,就是这种情况。这就是所谓的循环强引用

例:

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
    deinit { print("\(name) is being deinitialized") }
}

class Apartment {
    let unit: String
    init(unit: String) { self.unit = unit }
    var tenant: Person?
    deinit { print("Apartment \(unit) is being deinitialized") }
}
class TestViewController: UIViewController {
    var john: Persion? = nil
    var unit4A: Apartment? = nil
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = UIColor.red
        john = Persion(name: "John")
        unit4A = Apartment(unit: "4A")
        
    }
    
    deinit {
        print("TestViewController-deinit")
    }

}

在两个实例被创建和赋值后,下图表现了强引用的关系。变量 john 现在有一个指向 Person 实例的强引用,而变量 unit4A 有一个指向 Apartment 实例的强引用:

现在你能够将这两个实例关联在一起,这样人就能有公寓住了,而公寓也有了房客。注意感叹号是用来解包和访问可选变量 johnunit4A 中的实例,这样实例的属性才能被赋值:

class TestViewController: UIViewController {

    var john: Persion? = nil
    var unit4A: Apartment? = nil
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = UIColor.red
        
        john = Persion(name: "John")
        unit4A = Apartment(unit: "4A")
        //做关联
        john?.apartemtn = unit4A
        unit4A?.tenant = john
        
    }
    
    deinit {
        print("TestViewController-deinit")
    }

}

在将两个实例联系在一起之后,强引用的关系如图所示:

不幸的是,这两个实例关联后会产生一个循环强引用。Person 实例现在有了一个指向 Apartment 实例的强引用,而 Apartment 实例也有了一个指向 Person 实例的强引用。因此,当你断开 johnunit4A 变量所持有的强引用时,引用计数并不会降为 0,实例也不会被 ARC 销毁:

解决实例之间的循环强引用

Swift 提供了两种办法用来解决你在使用类的属性时所遇到的循环强引用问题:弱引用(weak reference)无主引用(unowned reference)

弱引用:前面加上 weak 关键字表明这是一个弱引用。ARC 会在引用的实例被销毁后自动将其弱引用赋值为 nil。并且因为弱引用需要在运行时允许被赋值为 nil,所以它们会被定义为可选类型变量,而不是常量。

注意 当 ARC 设置弱引用为 nil 时,属性观察不会被触发。

class Apartment: NSObject {
    
    let unit: String
    init(unit: String) {self.unit = unit}
     //设置弱引用
    weak var tenant:Persion?
    deinit { print("Apartment-deinit") }
}

现在,两个关联在一起的实例的引用关系如下图所示:

无主引用  和弱引用类似,前面加上关键字 unowned 表示这是一个无主引用。ARC 无法在实例被销毁后将无主引用设为 nil

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值