ARC (Automatic Reference Counting)
reference types (i.e. classes) 是儲存在heap中,要如何從heap釋放這些不使用的objects?Java使用garbage collection,但是swift並不使用garbage collection,而是ARC。
每次某個object被referenced,ARC就會增加此object的reference count,當然如果reference消失也會減少reference count,一個object的reference count為零的時候,就能從heap中釋放。
ARC是全自動的,programmer不能控制heap release。
影響ARC的方法
strong: 這是標準的reference,也就是某個var / let reference到的object,只在這個var/let 沒用到 (例如也deallocated / out of scope),才會decrease reference count。weak: 這只能用在 var/let是一個 Optional,因為他的語意是“如果某個object在heap中已經沒有人reference,那就deallocate它吧,我不care。如果還有人reference他,那我就持續weak reference他”。所以是一種消極的reference。當這個object因為沒人reference而被deallocated from heap的話,這個var/let 會被設定成nil,這也是為什麼只能用在Optional的關係。
unowned: 強制設定某個heap中的object不要再做ARC,這個等於破壞了ARC機制,非常少使用,通常用來打破memory cycle situation。
Memory Cycle
這有點類似deadlock,就是兩個object互相strong reference到彼此。Closures and ARC
closures是一個function object,是一個reference type所以存在heap中,他對他code block中的任何reference types會有strong reference。注意這個隱性的事實容易造成memory cycle,如果code block中的reference types又有strong reference到這個enclosing closure的話。假設有以下一個method:
client ViewController 假設傳入一個closure使用如下:
但是如果closure是trailing parameter,swift允許使用以下syntactic sugar:
甚至更進一步利用type inference簡化:
這樣寫很容易讓人忘記這事實上是一個trailing closure parameter,所以也就忘記了closure會對所有其內的reference types做strong reference。
還好swift compiler不允許這樣被compile,他希望programmer要明確知道這個closure有strong reference to self (outer class, i.e. ViewController):
注意如果不幸ViewController又有strong reference到這個closure的話,memory cycle 就會形成了!這種現象很可能發生,因為reference關係通常不明顯,需要考慮清楚。
解決此memory cycle:
1. 在closure中宣告一個local variable me,指向self (ViewController),這樣當然無助於break memory cycle,因為這又對self增加了一個strong reference(closure -> me -> self)。
不過如果採用unowned宣告me指向的self不要增加reference count:
me被使用的時候,如果self已經不在heap的話,此時就會crash,但是self是一個viewcontroller,所以這個情況crash也是合理的 (也是啦~)
不過為什麼不用weak? 其實用weak是比較preferred way,不過注意weak 一定是Optional才能宣告,所以要用?來防止self真的在heap中被deallocated:
沒有留言:
張貼留言