Swift 基礎學習(內存管理)

/*
    Swift 內存管理
*/

/*
(1)析構方法
對象的內存被回收前夕被隱式調用的方法.主要執行一些額外的操
作.
比如: 關閉文件,斷開網絡,釋放對象特有的一些資源等.
dealloc, MRC [obj release]
ARC, 弱化內存操作(Swift的析構方法,不用去管理內存).
*/
class FileHandle {
    var fd: Int32? //文件描述符
    init(path: String) {
        let ret = open(path, O_RDONLY)
        if (ret == -1) {
            fd = nil
        }else {
            fd = ret
        }
    }
    deinit {
        if let ofd = fd {

            close(ofd)
        }
        print("對象被銷燬,持有資源被釋放")
    }
}
//對象 (引用類型)何時被銷燬,對象沒有任何引用的時候.
var ofh: FileHandle? = FileHandle(path: "/etc/passwd")
//目前沒有任何的引用指向剛剛構造的對象.
//當註釋掉,該對象沒有被銷燬,所以就不會走deinit析構方法
//ofh = nil

/*
(2)析構方法的自動繼承-父類的析構方法會被自動調用,不需要
子類管理
*/
class SomeClass {
    deinit {
        print("SomeClass deinit!")
    }
}
class SubOfClass: SomeClass {
    deinit {
        print("SubOfClass deinit!")
    }
}
var osub: SubOfClass? = SubOfClass()
osub = nil

/*
(3)Swift語言的內存管理分析
*內存管理的對象-引用類型的對象(class類型)
*內存管理的原則:當沒有任何引用指向某個對象的時候,系統會自
動銷燬該對象.
*如何做到該原則:通過ARC技術
*/
class MenArc {
    deinit {
        print("deinit!")
    }
}
var t0 = MenArc()
var t1 = t0
var t2 = MenArc()
//t0,t1跟t2指向同一個對象
t0 = t2
t1 = t2

/*
(4)weak引用(弱引用)
*/
class Ref {
    deinit {
        print("Ref deinit!")
    }
    func test() {
        print("Test!")
    }
}
//強引用,默認得引用方式
var strongRef = Ref()//引用計數爲1
var strong1Ref1 = strongRef//引用計數爲2
//弱引用,weak引用非常安全得引用方式.
weak var weakRef = Ref() //ARC
//當去掉weak修飾時,並不會調用deinit析構方法
// var weakRef = Ref() //ARC
//弱引用,是一個可選類型.

weak var weakRef1: Ref? = Ref()
//不能通過強制解析進行訪問,編譯會通過,運行會崩潰
//weakRef1!.test()
//當引用時,需要判斷其是否爲nil
if let wr = weakRef1 {
    wr.test()
}

/*
(5)unowned引用(弱引用),不是可選類型
*/

/*
(6)循環強引用
ARC不是萬能的,它可以很好的解決內存過早釋放的問題,但是在
某些場合下不能很好的解決內存泄露的問題.
*/
class Person {
    let name: String
    init(name: String) {
       self.name = name
    }
    var apartmet: Apartment?
    deinit {
        print("\(name) is being deinitialized")
    }
}
class Apartment {
    let number: Int
    init(number: Int) {
        self.number = number
    }
    weak var tenant: Person?
    deinit {
        print("Apartment #\(number) is being deinitialized")
    }
}
var john: Person?
var number73: Apartment?
john = Person(name: "john Appleseed")
number73 = Apartment(number: 73)

john!.apartmet = number73
number73!.tenant = john

//兩個對象沒有被銷燬,但是我們沒有辦法再訪問它們了,內存泄露
//解決辦法:將某一個屬性設置爲弱引用即可weak, 在var tenant前面添加關鍵字weak
john = nil
number73 = nil

/*
(7)unowned解決循環強引用
*/
class Customer {
    let name: String
    var card: CreditCard?
    init(name: String) {
        self.name = name
    }
    deinit {
        print("\(name) is being deinitialized")
    }
}
class CreditCard {
    let number: UInt64
    //解決循環引用
    unowned let customer: Customer
    init(number: UInt64, customer: Customer){
        self.number = number
        self.customer = customer
    }
    deinit{
        print("Card #\(number) is being deinitalized")
    }
}
var john1: Customer?
john1 = Customer(name: "John1 Appleseed")
john1!.card = CreditCard(number: 1245_5678_9012_3456, customer: john1!)
john1 = nil
(6)未用弱引用weak修飾前這4行代碼對應以下圖內容:
john = Person(name: "john Appleseed")
number73 = Apartment(number: 73)

john!.apartmet = number73
number73!.tenant = john

這裏寫圖片描述

對應以下內容:
//導致內存泄露,john的apartment和number73的tenant兩個對象還互相持有導致我們的內存泄露
john = nil
number73 = nil

這裏寫圖片描述

通過將某個屬性設置爲弱引用weak時如圖所示:
weak var tenant: Person?
john = Person(name: "john Appleseed")
number73 = Apartment(number: 73)

john!.apartmet = number73
number73!.tenant = john

這裏寫圖片描述

對應以下圖示:
john = nil
number73 = nil

這裏寫圖片描述

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章