Swift学习笔记-自动引用计数

引用计数应用于类的实例。结构体和枚举类型是值类型,不是引用类型,也不是通过引用的方法存储和传递。

弱引用

声明属性或者变量时,在前面加上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)"
        }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,应该用无主引用。

你可能感兴趣的:(Swift学习笔记-自动引用计数)