引用计数应用于类的实例。结构体和枚举类型是值类型,不是引用类型,也不是通过引用的方法存储和传递。
弱引用
声明属性或者变量时,在前面加上weak关键字表明这是一个弱引用。(当arc设置弱引用为nil时,属性观察不会被触发)
class Person {
let name : String
init(name:String) {
self.name = name
}
var apartment : Apartment?
deinit {
print("\(name) is being delloc")
}
}
class Apartment {
let name : String
init(name:String) {
self.name = name
}
weak var person : Person?
deinit {
print("\(name) is being empty")
}
}
var building : Apartment?
var person : Person?
building = Apartment(name: "爱情公寓")
person = Person(name: "美嘉")
building!.person = person
person!.apartment = building
person = nil
无主引用
和弱引用不同的是,无主引用在其他实例有相同或者更长的生命周期时使用。在关键字前添加 unowned表示。
重要
使用无主引用,你必须确保引用始终指向一个未销毁的实例。
如果你试图在实例被销毁后访问该实例的无主引用,会触发运行时错误。
class Customer {
let name : String
var card : CreditCard?
init(name:String) {
self.name = name
}
deinit {
print("Custimer delloc")
}
}
class CreditCard {
let name : String
unowned var customer : Customer
init(name:String,cutomer:Customer) {
self.name = name
self.customer = cutomer
}
deinit {
print("CreditCard delloc")
}
}
var john : Customer?
john = Customer(name: "John")
john?.card = CreditCard(name: "card", cutomer: john!)
john = nil
Person和Apartment的例子展示了二个属性的值都允许为nil,这种场景适合用弱引用来解决。
Customer和CreditCard的例子展示了一个属性的值不允许为nil,这种场景适合用无主引用解决。
当两个属性均可不为nil且互相引用时,如下
class Country {
let name : String
var city : City!
init(name:String,cityName:String) {
self.name = name
self.city = City(name:cityName,country:self)
}
}
class City {
let name : String
unowned let country : Country
init(name:String,country:Country) {
self.name = name
self.country = country
}
}
解决闭包引起的循环引用
以下是造成了循环引用的代码。
class HTMLElement {
let name : String
let text : String?
lazy var asHTML : () -> String = {
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("销毁")
}
}
解决方法:声明每个引用为弱引用或者无主引用。
注意
swift有以下要求:只要在闭包内使用self成员,就要用self.name,self.someMethod(),而不是name,someMethod()。
使用无主引用:在闭包和捕获的实例总是互相引用并且总是同时销毁时,将闭包内的捕获定义为无主引用。
弱引用:在被捕获的引用可能会变为nil时,将闭包内捕获的定义为弱引用。
如果被捕获的引用绝对不会变为nil,应该用无主引用。