關於swift ARC (上)

Swift使用自動引用計數的機制來跟蹤和管理應用程式的內存,ARC全名為(Automatic Reference Counting),通常情況下,swift的內存管理機制會一直起著作用,你無須自己來考慮內存的管理,ARC會在類別的實例不再被使用時,自動釋放其佔用的內存。

為什麼又叫做自動引用計數呢?下面用Playground來演示一下範例:

如上圖所見,假設變數a 以classA型態初始化,然後把a給了a2跟a3,這時三個變數都可以呼叫使用classA的方法hello()。

這時如果我把a跟a2給手動釋放掉的話….如下圖所見,a3依然可以使用 class A Instance的func hello()

可以理解為A類別的新實例賦值給了 a、a2、a3等變數,所以三個變數到A類別的新實例之間建立了強參考,正是因為強參考的緣故,ARC會保證class A 的Instance保持在內存中不被銷毀。

以Instance裡面的property來測試….由下圖可見,就算a被手動釋放掉,a2跟a3也因為ARC強參考的機制,依然可以參考的到值。

這時該怎麼解決實例之間的強參考問題呢?

如下圖示範

只要在宣告的時候使用弱參考,ARC就會銷毀被參考的實例。

宣告屬性或變數時,在前面加上weak關鍵字表明這是一個弱參考。

由圖片可見,釋放掉a與a2以後a3也失去了強參考實例,因而也釋放了class A 的記憶體。

疑問來囉?為什麼要使用弱參考呢?什麼情況下會使用?

舉一個叫做Strong Reference Cycles Between Class Instances例子

為了示範正常情況,我先把c.b = self 給註解了,此時可以看見有執行到deinit區塊的print方法,這個deinit方法是在釋放該記憶體的時最後會執行的一個方法,用這個方式來簡易測試,是否成功釋放了該記憶體。

一旦c.b = self,產生了這種我中有你、你中也有我的情況,就會導致兩個類別實例互相保持著對方的強參考,並讓對方不被銷毀。

發生這種情況就叫做Retain Cycle。

這時即使你要手動釋放b裡面的c裡面的b也會報錯,因為在邏輯上,編譯器認為b已經被你給釋放掉了,所以會報錯,導致該記憶體將永遠無法被釋放。

來思考看看,該怎麼解決Retain Cycle 這種情況呢?

沒錯,聰明的各位應該猜到了,就是宣告時使用弱參考weak關鍵字!

編譯後印出deinit區塊的print func,代表該記憶體成功被釋放掉了。

ARC(上)暫時介紹到這邊,下則心得會分享使用protocol或closure會發生的Retain Cycle情況及該怎麼解決!!


Originally published at medium.com.