1、Swift采用ARC(自動引用計數,Automatic Reference Counting),程序員不用關心對象釋放的問題,編譯器在編譯時在合適的位置插入對象內存釋放代碼。
ARC對引用類型的管理,即類,值類型是由處理器自動管理。
2、引用計數:每個Swift類創建的對象都有一個內部計數器,這個計數器跟蹤對象的引用次數。
原理:對象被創建是,引用計數為1,每次對象被引用的時候,引用計數加1,當不需要的時候對象引用斷開(賦值nil),引用計數減1,當對象的引用計數為0是,對象的內存才被釋放。
ref1 = Employee()
ref2 = ref1
ref3 = ref1
ref1 = nil
ref2 = nil
ref3 = nil
3、強引用循環
當兩個對象的存儲屬性互相引用對方的時候,一個對象釋放的前提是對方先釋放,另一對象釋放的前提也是對方先釋放,這樣最后誰都不能釋放,從而導致內存泄漏。
classEmployee {
...
var dept:Department?
init(no:Int, name:String, job:String, salary:Double) {
...
}
deinit{
...
}
}
classDepartment {
...
var manager:Employee?
init(no:Int, name:String) {
...
}
deinit{
...
}
}
4、解決強引用循環的方式:弱引用、無主引用
弱引用:weak,允許一個對象不采用強引用的方式引用另一個對象,適用于引用對象可以沒有值的情況
無主引用:unowned,允許一個對象不采用前引用的方式引用另一個對象,使用域引用對象永遠有值
弱引用:
classEmployee {
...
weakvardept:Department?
init(no:Int, name:String, job:String, salary:Double) {
...
}
deinit{
...
}
}
classDepartment {
...
varmanager:Employee?
init(no:Int, name:String) {
...
}
deinit{
...
}
}
無主引用:
classEmployee {
...
vardept:Department?
init(no:Int, name:String, job:String, salary:Double) {
...
}
deinit{
...
}
}
classDepartment {
...
unownedvarmanager:Employee?
init(no:Int, name:String) {
...
}
deinit{
...
}
}
5、閉包中的強引用循環
閉包實質上是函數類型,也是引用類型,可能在閉包和上下文捕獲變量(或常量)之間出現強引用循環問題。
只有將一個閉包賦值給對象的某個屬性,并且這個閉包體使用了該對象self,才會產生閉包強引用循環。
classEmployee {
...
init(no:Int, firstName:String, lastName:String, job:String, salary:Double) {
...
}
deinit{
...
}
lazyvarfullName: () ->String= {
returnself.firstName+"."+self.lastName
}
}
self在閉包匯總使用,屬性必須聲明為lazy,所有屬性初始化完成后,self表示的對象才能被創建
6、解決閉包強引用循環方式:弱引用、無主引用
弱引用:閉包內捕獲對象可以為nil時使用
無主引用:閉包內捕獲對象絕對不會為nil時使用
有參數情況下:
lazy var 閉包:<閉包參數列表> -> <返回值類型> = {
[unowned 捕獲對象]?<閉包參數列表> -> <返回值類型> in 或者
[weak 捕獲對象]?<閉包參數列表> -> <返回值類型> in
閉包內容
}
classEmployee {
...
init(no:Int, firstName:String, lastName:String, job:String, salary:Double) {
...
}
deinit{
...
}
lazyvarfullName: (String, String) ->String= {
[weak self] (firstName: String, lastName: String) -> String in
...
}
}
無參數情況下:
lazy var 閉包:() -> <返回值類型> {
[unowned 捕獲對象] in 或者
[weak 捕獲對象] in
閉包內容
}
classEmployee {
...
init(no:Int, firstName:String, lastName:String, job:String, salary:Double) {
...
}
deinit{
...
}
lazyvarfullName: () ->String= {
[weakself] () ->Stringin
...
}
}