🔰escaping closure
解說
👉 本例改編自:官方 Escaping Closures (Swift)
💾 replit
⭐️ 抓住物件
注意看:
同樣是「修改屬性 x」這樣一個動作,doItLater
跟 doItNow
的寫法就不同:
doItNow 寫的是: { x = 200 }
doItLater 寫的是: { self.x = 100 } ,如果不指定 self 會出現 compiler 錯誤。
為什麼有這樣的區別呢 ❓
這牽涉到物件參照(object reference)的問題。假設: let a = A()
,這時執行: a.changeX()
這個物件方法就開始逐行執行:
doItLater { self.x = 100 }
doItNow { x = 200 }
當執行到 doItNow { x = 200 }
時,因為物件 a
顯然還活著, 所以如果要改變 a.x = 200
當然不是問題。
但 doItLater { self.x = 100 }
這一行,單純只是把 { self.x = 100 }
這項工作存起來而已,所以我們如何保證當「以後」真正執行時,self
(也就是本例的 a
) 物件還存活著?
所以這裡就牽涉到一個 Swift 的絕活,它就是「硬性規定」你一定 要寫成 { self.x = 100 }
的形式,而不是 { x = 100 }
, 來「抓住」(capture) self
(也就是本例的 a
) 物件,保證讓這個物件不會自動從記憶體中清除,所以將來執行 { self.x = 100 }
時才不會出問題。
物件抓得太緊 ❓
至於說「將物件抓住」這個做法會不會產生 strong reference cycle,導致物件無法清除,進而產生記憶體流失 (memory leak),那就是程式設計師要考慮如何解決的另一個問題了。
Last updated