Swift篇——ARC中循环引用问题

如果你有过实际iOS开发经验,尤其是OC时代的,那么你一定遇到过这样的一个问题,那就是循环应用,于是就有了各种文文章,各种解决方式实现这样的问题,但是这种情况到了Swift里面依然没有办法避免的,只是Swift里面似乎考虑到了OC中欠缺的地方,同时也为了我们能更好的处理这样的问题,给出了对应的方案……

一、几个用到的关键概念

弱引用(weak):

不会增加自动引用计数,必须为可选类型变量,因为弱引用在引用计数为0的时候,会自动赋为nil。在swfit中,可以赋值为nil的为可选类型

无主引用(unonwed):

不会增加自动引用计数,必须为非可选类型。在ARC销毁内存后,不会被赋为nil,所以在访问无主引用的时候,要确保其引用正确,不然会引起内存崩溃。

隐式解析可选类型:

在初始的时候可以为nil,但是第一次赋值以后便会一直有值。语法是在变量后面加上感叹号(例如var name:String!)。使用该类型只需要正常调用,不需要像可选类型那样做判断。

二、类实例之间的循环引用

1、实例A可选包含实例B的引用,实例B可选包含实例A的引用-用弱引用来解决

公寓不一定有住户,住户也不一定在公寓里

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

class Apartment {
    let number: Int
    init(number: Int) { self.number = number }
    weak var tenant: Person?
    deinit { println("Apartment #\(number) is being deinitialized") }
}

var john: Person?
var number73: Apartment?
john = Person(name: "John Appleseed")
number73 = Apartment(number: 73)
john!.apartment = number73
number73!.tenant = john

2、实例A可选包含实例B,实例B一定包含实例A-用无主引用解决

用户可能没有信用卡,但是信用卡一定会有用户。由于信用卡一定有用户,所以不是可选类型,不能用弱引用,swift中提供的无主引用是简单便捷的解决方案。

class Customer {
    let name: String
    var card: CreditCard?
    init(name: String) {
        self.name = name
    }
    deinit { println("\(name) is being deinitialized") }
}

class CreditCard {
    let number: Int
    unowned let customer: Customer
    init(number: Int, customer: Customer) {
        self.number = number
        self.customer = customer
    }
    deinit { println("Card #\(number) is being deinitialized") }
}

var john: Customer?
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

3、A一定包含B,B一定包含A - 用隐式解析+无主引用解决

国家一定包含首都,首都也一定在一个国家里

class Country {
    let name: String
    let capitalCity: City!
    init(name: String, capitalName: String) {
        self.name = name
        self.capitalCity = City(name: capitalName, country: self)
    }
}
class City {
    let name: String
    unowned let country: Country
    init(name: String, country: Country) {
        self.name = name
        self.country = country
    }
}
坚持原创技术分享,您的支持将鼓励我继续创作!