上一篇講到沒有辦法釋放記憶體的部分,明明不會有人用到該記憶體位置,但記憶體位置一直都是被佔滿的狀態。程式內太多這種情況就會造成 Memory Leak。
Swift 提供了兩種方法來處理強類型的屬性:弱引用(weak)和無主引用(unowned)。
通常當一個屬性被建立時,除非 Reference 被設置為 weak 或 unowned,否則會預設為 strong
weak也就表示他所參考的記憶體位址裡的東西只是弱引用,也就是說有東西我就引用,沒有東西的話我就不引用。且弱引用不會增加reference count。
ARC會在被引用的實例被釋放是自動地設置弱引用為 nil。所以弱引用的值有可能有也有可能沒有,它們一定得是optional
class Animal{
var animalSpecies :String
init(animalSpecies: String) {
self.animalSpecies = animalSpecies
print("\(animalSpecies) is init.")
}
weak var belong: Zoo?
deinit {
print("\(animalSpecies) is deinit.")
}
}
class Zoo{
var owner: String
init (owner: String){
self.owner = owner
print("\(owner)'zoo is init.")
}
weak var ownership: Animal?
deinit {
print("\(owner)'zoo is deinit.")
}
}
var leo: Zoo? = Zoo(owner: "Leo")
var lion: Animal? = Animal(animalSpecies: "lion")
leo = nil
//結果如下
//Leo'zoo is init.
//lion is init.
//Leo'zoo is deinit.
和Weak類似,Unowend不會保持住引用的實例。但不同於Weak,Unowend假定是永遠有值。所以Unowend的property永遠不會是nil。在Unowend的狀況下記憶體位置一定有東西,一旦沒被參考到,記憶體空間會馬上釋放,直到下一次被引用
class Animal{
var animalSpecies: String
var animalCount: Count?
init(animalSpecies: String) {
self.animalSpecies = animalSpecies
print("\(animalSpecies) is init.")
}
deinit {
print("\(animalSpecies) is deinit.")
}
}
class Count {
var countNumber: Int
unowned var whatAnimal: Animal
init(countNumber: Int, whatAnimal: Animal ) {
self.countNumber = countNumber
self.whatAnimal = whatAnimal
}
deinit {
print("\(countNumber) is deinit.")
}
}
var lion: Animal? = Animal(animalSpecies: "Lion")
lion!.animalCount = Count(countNumber: 100, whatAnimal: lion!)
lion = nil
//結果如下
//Lion is init.
//Lion is deinit.
//100 is deinit.
現在lion指向的實體參考計數為1,而現在lion內屬性whatAnimal參考計數也為1。而Count的whatAnimal屬性因為是無主參考指向lion,所以不會增加參考計數。
此時用nil將lion指向的實體強參考斷開,這個實體的參考計數為0,實體會被釋放,指向Count實體的強參考也會被斷開。
結果
以上例子介紹class Animal跟class Count之間關係。有保留動物的位置不一定會有數量,有數量一定會有動物。
參考APPCODA的圖片,可以讓我們對Reference更加理解