013-Swift3.0之循环强引用
一、解决实例属性之间的循环强引用
1.弱引用
// 定义一个Person(人)类 class Person { let name: String var apartment: Apartment? // 并不是每个人都有公寓,所以为可选型 // 构造函数 init(name: String) { self.name = name } // 析构函数 deinit { print("\(name)被销毁") } } // 定义一个Apartment(公寓)类 class Apartment { let name: String // 注意:这里是弱引用,因为Person对Apartment强引用,Apartment对Person如果还是强引用,就会造成循环强引用,造成内存泄露 weak var tenant: Person? // 并不是每个公寓都有对应的人,所以为可选型 // 构造函数 init(name: String) { self.name = name } // 析构函数 deinit { print("\(name)被销毁!") } } // 初始化创建一个Person(人)对象 var frank = Person(name: "Frank") // 初始化创建一个Apartment(公寓)对象 var wanda = Apartment(name: "万达") // 如果不是Apartment对Person的弱引用,就会造成彼此的循环强引用,造成内存泄漏 frank.apartment = wanda wanda.tenant = frank

2.无主引用
// 定义一个Customer(拥有者)的类 class Customer { let name: String var card: CreditCard? // 不是所有人都有信用卡,所以是可选型 init(name: String) { self.name = name } deinit { print("\(name)被销毁") } } // 定义一个CreditCard(信用卡)的类 class CreditCard { let number: UInt64 unowned let customer: Customer // 每一张信用卡有且仅有一个拥有者(无主引用) init(number: UInt64, customer: Customer) { self.number = number self.customer = customer } deinit { print("卡号为\(number)的信用卡被销毁") } } // 定义一个Customer对象 var emma: Customer? emma = Customer(name: "Emma") emma!.card = CreditCard(number: 1234_5678_3434_9009, customer: emma!) // 绑定信用卡 // 绑定信用卡的时候,其实就存在一个循环引用,好在信用卡只是对于拥有者是无助引用,所以没有造成循环强引用

3.无主引用以及隐式解析可选属性
// 定义一个Country(国家)类 class Country { let name: String // 这里capitalCity默认值为nil,但当Country一旦完成初始化任务,它的值就可以直接引用 var capitalCity: City! // 每一个国家有且仅有一个省会城市(隐式解析可选属性) init(name: String, capitalName: String) { self.name = name self.capitalCity = City(name: capitalName, country: self) } } // 定义一个City(城市)类 class City { let name: String unowned let country: Country // 每一个城市有且仅被一个国家拥有(无主引用) init(name: String, country: Country) { self.name = name self.country = country } } // 定义一个Country对象 var country = Country(name: "China", capitalName: "Beijing") print("\(country.name)的首都是\(country.capitalCity.name)")
1)当两个循环引用属性均为可选类型时,也就是均允许为nil,并且会产生潜在的循环强引用,这种场景最适合通过弱引用
2)当两个循环引用属性中一个属性为可选类型时,也就是只有一个允许为nil,而另一个属性的值不允许为nil,这也可能会产生循环强引用,这种场景适合通过无主引用
3)当两个循环引用属性都必须有值,并且初始化完成后永远不会为nil,这种场景需要一个类使用无主属性,而另外一个类使用隐式解析可选属性
二、解决闭包产生的循环强引用
// 定义一个HTMLElement(HTML标签)类 class HTMLElement { let name: String let text: String? lazy var asHTML: () -> String = { [unowned self] in if let text = self.text { return "<\(self.name)>\(text)</\(self.name)>" } else { return "<\(self.name) />" } } init(name: String, text: String? = nil) { self.name = name self.text = text } deinit { print("\(self.name)标签被销毁") } } var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world") print(paragraph!.asHTML())


浙公网安备 33010602011771号