Swift 自動引用計數(ARC)

2021-08-08 12:43:59 字數 3649 閱讀 8595

swift使用自動引用技術(arc)這一機制來跟蹤和管理應用程式的記憶體。通常情況下我們不需要去手動釋放記憶體,因為arc會在類的例項不再被使用時,自動釋放其占有的記憶體。

但在有些時候我們還是需要在**中實現記憶體管理。

class

person

deinit

}// 值會被自動初始化為nil,目前還不會引用到person類的例項

var reference1: person?

var reference2: person?

var reference3: person?

// 建立person類的新例項

reference1 = person(name: "runoob")

//賦值給其他兩個變數,該例項又會多出兩個強引用

reference2 = reference1

reference3 = reference1

//斷開第乙個強引用

reference1 = nil

//斷開第二個強引用

reference2 = nil

//斷開第三個強引用,並呼叫析構函式

reference3 = nil

以上程式執行輸出結果為:

runoob 開始初始化

runoob 被析構

在上面的例子中,arc 會跟蹤你所新建立的 person 例項的引用數量,並且會在 person 例項不再被需要時銷毀它。

然而,我們可能會寫出這樣的**,乙個類永遠不會有0個強引用。這種情況發生在兩個類例項互相保持對方的強引用,並讓對方不被銷毀。這就是所謂的迴圈強引用。

class

person

var apartment: apartment?

deinit

}class

apartment

var tenant: person?

deinit

}// 兩個變數都被初始化為nil

var runoob: person?

var number73: apartment?

// 賦值

runoob = person(name: "runoob")

number73 = apartment(number: 73)

// 意感嘆號是用來展開和訪問可選變數 runoob 和 number73 中的例項

// 迴圈強引用被建立

runoob!.apartment = number73

number73!.tenant = runoob

// 斷開 runoob 和 number73 變數所持有的強引用時,引用計數並不會降為 0,例項也不會被 arc 銷毀

// 注意,當你把這兩個變數設為nil時,沒有任何乙個析構函式被呼叫。

// 強引用迴圈阻止了person和apartment類例項的銷毀,並在你的應用程式中造成了記憶體洩漏

runoob = nil

number73 = nil

swift 提供了兩種方法用來解決你在使用類的屬性時所遇到的迴圈強引用問題:

class

module

var sub: submodule?

deinit

}class

submodule

weak var topic: module?

deinit

}var toc: module?

varlist: submodule?

toc = module(name: "arc")

list = submodule(number: 4)

toc!.sub = list

list!.topic = toc

toc = nil

list = nil

以上程式執行輸出結果為:

arc 主模組

子模組 topic 數為 4

class

student

deinit

}class

marks

deinit

}var

module: student?

module = student(name: "arc")

module!.section = marks(marks: 98, stname: module!)

module = nil

以上程式執行輸出結果為:

arc

學生的分數為 98

迴圈強引用還會發生在當你將乙個閉包賦值給類例項的某個屬性,並且這個閉包體中又使用了例項。這個閉包體中可能訪問了例項的某個屬性,例如self.someproperty,或者閉包中呼叫了例項的某個方法,例如self.somemethod。這兩種情況都導致了閉包 「捕獲」 self,從而產生了迴圈強引用。

下面的例子為你展示了當乙個閉包引用了self後是如何產生乙個迴圈強引用的。例子中定義了乙個叫htmlelement的類,用一種簡單的模型表示 html 中的乙個單獨的元素:

class htmlelement  else 

}init(name: string, text: string

?= nil)

deinit

}// 建立例項並列印資訊

var paragraph: htmlelement?

= htmlelement(name: "p", text: "hello, world")

print(paragraph!

.ashtml())

htmlelement 類產生了類例項和 ashtml 預設值的閉包之間的迴圈強引用。

例項的 ashtml 屬性持有閉包的強引用。但是,閉包在其閉包體內使用了self(引用了self.name和self.text),因此閉包捕獲了self,這意味著閉包又反過來持有了htmlelement例項的強引用。這樣兩個物件就產生了迴圈強引用。

解決閉包引起的迴圈強引用:在定義閉包時同時定義捕獲列表作為閉包的一部分,通過這種方式可以解決閉包和類例項之間的迴圈強引用。

當閉包和捕獲的例項總是互相引用時並且總是同時銷毀時,將閉包內的捕獲定義為無主引用。

相反的,當捕獲引用有時可能會是nil時,將閉包內的捕獲定義為弱引用。

如果捕獲的引用絕對不會置為nil,應該用無主引用,而不是弱引用。

class htmlelement  else 

}init(name: string, text: string? = nil)

deinit

}//建立並列印htmlelement例項

var paragraph: htmlelement? = htmlelement(name: "p", text: "hello, world")

print(paragraph!.ashtml())

// htmlelement例項將會被銷毀,並能看到它的析構函式列印出的訊息

paragraph = nil

以上程式執行輸出結果為:

hello, worldp>

p 被析構

ARC(自動引用計數)

arc arc是automatic reference counting 自動引用計數 的縮寫,是ios5一同推出的新特性,但是ios4.3也支援arc,只是不能使用weak。使用arc,不需要再retain release autorelease,因為編譯器會在合適的地方自動的插入retain r...

ARC自動引用計數

選擇專案的屬性檔案 搜尋 automatic reference objective c automatic reference counting yes arc 並不是gc在執行中判斷引用計數是否為0,從而清除記憶體。而是在 編譯之前通過靜態分析工具analyze自動生成記憶體管理 開啟arc後,...

swift自動引用計數

在少數情況下,arc為了能幫助你管理記憶體,需要更多的關於你的 之間關係的資訊 引用計數僅僅應用於類的例項,結構體和列舉型別是值型別,不是引用型別,也不是通過引用的方式儲存和傳遞 為了使之成為可能,無論你將例項賦值給屬性,常量或者是變數,屬性,常量或者變數,都會對此例項建立強引用。之所以稱之為強引用...