線上收聽與節目筆記
本集竟然有人 escape!那我們就順勢來回應與 @escaping 有關的 #weakself挑戰賽吧!為什麼 Swift closure 的 [weak self] 要加中括號呢?weak、unowned 你分得清楚差別嗎?一起來參與挑戰吧。
weak self 挑戰賽
- 小綠的挑戰推文
- 何謂 escaping、nonescaping closure
- 何時用 weak、unowned,或是不用
Closure 的行為
- 搭配服用的程式範例
- closure 預設會 capture (strong reference) 外部變數
- capture list 會生成一份 copy
Escaping 和 Nonescaping
- function return 後還會發生的叫做 escaping
- 有機會造成 retain cycle
Weak 和 Unowned 的運作原理
- Swift 的 reference instance 是個 HeapObject
- HeapObject
- weak reference 會為 instance 建立 side table 用來計算數目
- Swift Ownership Manifesto
- Objective-C 的 ARC 功能如果不是因為創立全新語言 Swift 時追求 memory safety,恐怕從來不會出現。有興趣的朋友可以去聽 The Swift Community Podcast Ep.1。
何時用 weak 或是 unowned?
- closure 生命週期與對象生命周期一致時,使用 unowned
- weak 有較多記憶體消耗
- 要了解程式碼裡大家的生命周期啊
挑戰賽小結
- closure 會捕捉外部使用的變數,有可能造成 retain cycle
- weak 和 unowned 有不同的機制與生命週期
- 沒有 retain cycle 不用 weak / unowned
- weak 有額外的記憶體與性能消耗(可忽略)
工程師的 escape
13 最近在玩 Apple Arcade
- 13 的 Apple #ArcadeReview 連載中
- iPad mini 超適合玩 Apple Arcade 的,又輕又快又平💸
本集播出後的後續討論與內容更正
本集內容播出後,有推友向我們回饋有些內容觀念混淆也提出了正確和清楚的說法,非常感謝這些推友們,我們非常樂見這樣的抓漏討論!這些討論和更正整理如下:
Swift 的 closure 與 Objective-C 的 block
這裡在節目和後續討論中把兩個東西混在一起說,兩者之間的差異如下:
- Swift 的 closure 是 reference type,不需要關心 copy 或在 heap 、 stack 的問題
- OC 裡的 block 有 stack / global / heap 三種,ARC 的環境中基本上沒有 stack block
- OC 裡的 block copy ,對 stack block 會將它移到 heap 上,已在 heap 的就是 retain count 加一
- OC 裡的 block 沒有 escaping 的概念
- Twitter 原文1,原文2
weak 以及 unowned 的使用策略
推友提到另一個很好的切入觀點,從程式碼的維護觀點出發,當程式迭代,生命周期和從屬關係可能發生變化,而這些 unowned 可能帶來維護上的負擔,詳見 Twitter 原文。
Swift 裡的 Ownership 提案與現況
在節目提到這個時我的了解都是來自於和友人的討論,顯然有些地方講得不正確,將正確的觀念與現況整理如下:
- Ownership 的概念其實很簡單,大意是 instance 都有自己的 owner,當 owner 的 lifetime 結束,這個 instance 應該也要隨之銷毀
- Rust 已經有非常完整的實做,可以在記憶體上有更安全的保證,有幾點是目前 Swift 無法保證的安全問題:
- Dangling pointer
- Free after use
- Strong reference (retain) cycle
- Ownership 在 Swift 的實作其實就是體現在 ARC 裡的 strong reference,這裡就是我們熟悉的,當 retain count 變成 0,instance 就會被銷毀,這裡是實作在 Swift 語言本身的機制,也是我們本集的主要內容。
- Ownership manifesto 提案內容是在一般開發者無感的底層實作(ARC)之外,提供讓開發者以加標籤的方式(shared、moveOnly 等)以使用 ownership 的功能,這些功能最主要都圍繞在獨佔性原則(Law of Exclusivity)
- 承上,Swift 裡主要想解決的問題在 copy 的性能問題,主要是針對 struct 的 copy on write
- 照 manifesto 裡的內容,若要運用勢必會對現行的程式碼帶來改變,但他們有一再強調改變會盡量小且必要(but who knows)
- 而且應該是要和 ARC 共存,並不是取代(這是我個人讀完的見解)
- 就我所知目前應該尚未有可用的實作
- 參考資料:推友原文,一篇分析 ownership 在 Rust 與 Swift 差異的論文,喵神翻譯的 Ownership Manifesto
更多 weak self
- 主持人 一三、波肥、喬喬
- 官網 https://weakself.dev
- Twitter @weak_self
- 提問箱
- 贊助 weak self