在 iOS 的開發語言之中,不論是 Objective-C 或者 Swift,你或許都有看過這個詞
weak
你可能會知道它可以避免 retain cycle,但其背後的觀念是什麼?
ARC
在目前大家所熟悉的開發環境之中,記憶體的管理是由 iOS 或 macOS 自行去解決的;它會在你宣告或者呼叫物件的時候,替它在計數器上 +1,而當你用不到時,便會 -1。 當計數器為零的時候,便釋放掉這個物件的記憶體位置。 舉個例子,我在某個 ViewController 裏頭,宣告了一個變數 A 及執行一個異步的閉包(closure),並在裡頭使用到 A。 此時,A 在剛剛宣告產生的時候,計數器會是 +1,而在閉包內被使用到,故計數器會再 +1,所以在閉包執行時,它會是 2。
那如果我們這時候,離開了 ViewController,照理說其裡頭的 instance 應該都要被釋放記憶體位置;但因為異步閉包的關係,我們無法確定在離開的時候,異步閉包是否在其他執行緒中正在執行,造成 A 的計數器仍為 1,且會繼續執行異步閉包的內容。
weak 簡單來說就是,它並不會讓這個物件在計數器上 +1,並且在記憶體被釋放之後,指標會指向 nil;而在 Objective-C 及 Swift 裏頭,nil 的物件呼叫方法時,是不會造成崩潰的。
retain cycle 就像是 A 使用到 B,並且 B 也使用到 A,兩者互相幫對方在計數器上 +1,那僅管我們今天離開了這個畫面,系統幫 A – 1 之後,仍然會因為 B 有使用到它,故釋放不掉 A,而 A 有使用 B,所以 B 也釋放不掉。(很饒舌,我知道) 所以在 A 裡頭使用到 B 時,將 B 宣告成 weak B,便不會幫 B 在計數器上記上一筆;當 A 要被釋放掉的時候,也不會因為 B 使用 A,而釋放不掉。