關於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.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.