

Discover more from 波報 | Pofat 的 Swift 中文電子報
💬 Pofat 的話
這週開始 review 的 SE 將會是個很重要的里程碑,讓 Swift 本身擁有原生的響應能力,論壇上也有針對這提案的精彩回應,錯過可惜便全收錄在本週內容了。
也請訂閱 Patreon 來支持我🙏
🗣️ On Swift Forum
SE-0395 Observability (Reviewing)
觀察者模式與 Reactive Programming 經過許多語言和框架的考驗,無疑是現代(好像也很久了)重要的開發模式之一,Swift 本身也有 Combine 來回應這個需求,更是 SwiftUI 畫面與資料綁定的核心基礎。
然而 Combine 僅限於 Darwin 平台使用,與 Swift 全平台制霸的野望不符;現下的 KVO 雖然表面上有 KeyPath 帶來的 type safe 表象,底下仍然是透過字串來呼叫 ObjC runtime api,此外功能也過於陽春,無法觀察 computed property 也無法有更複雜的組合觀察邏輯。
這個提案可以理解為 Swift 原生的進化 KVO ,也考慮了 Swift Concurrency 的整合使用,這裡應該滿足的需求有:
語法上容易標記為可被觀察對象Graph Transaction Model.,且也很容易開始使用
要理會 access control (KVO 基於 Objc runtime,基本上沒有 access control)
可觀察 computed property ,無論其來源基於內部或外部的資料
多個觀察整合的通知需基於其(transactions of graph),而非單一物件
以上皆透過引進 Observable 來達成,它從三個方面支援與數值變化的互動:「可觀察特定數值的變化」,「將變化觀察連結至特定的 actor 」與「UI 間的協作」。宣告方式就是加上 @Observable
最主要的使用方式即觀察單一值,或複數對象的組合。這裡通知發生的時機點即是設值的當下,可視為介於 willSet
和 didSet
之間;發的地點則是在指定的 actor 上,預設是 MainActor(實際變化可能發生在不同 actor 中)
最後是定義觸發 computed property 變化通知的來源,預設是任一 stored property 的變化皆會觸發
是一個 protocol,定義了上述三種主要使用介面,
這之中 Observable@Observable
則是一個 Swift Macro ,用來生成程式碼,這裡真是用到極致的一個實例,短短的一個 macro 做了非常的多的事:
宣告該 class 遵循 Observable protocol與生成實作,還有 extension 裡方便使用的介面(生成程式碼前後的截圖放在最後)
新增一個 registrar 來負責所有觀察註冊和信號處理
新增一個 storage 存於所有 stored property 以追蹤相關存取
將所有 stored property 改成具有 getter 和 setter 的 computed property
生成 initializer
生成後該物件的主要架構如下(想看生成前後的程式碼請點此):
這裡其實沿襲 @ObservableObject
原理的想法,原本是 compiler 會特別為標記 @Published
的 property 生成設值時會觸發 objectWillChange
的相關程式碼,只是再也不用標記煩人的 @Publihsed
。顯然這個是想取代 @ObservableObject
並彌補其不足之處,因為使用時 UI (這裡特指 SwiftUI)並不一定依賴所有的 @Published
,但是任一個的變化都會造成新的 render,而 ObservationTracking
可以追蹤某個 scope 中有哪些變數被存取,而只對該些變數的變化發通知,這裡在 SwiftUI 有很大的潛力,可以更精確地只在真正介意的值變化時發到通知。
做為真正類型安全和進階功能的解決方案,的確是有解決當前開發者們的一大需求,不過這裡要提醒一件事,computed property 其實就是一個 method ,官方有說明請開發者自律地讓它為 O(1), 如果大家不小心沒達成,又將其做為觀察對象時,可能會有效能問題產生。
Some suggestions for Swift Observation
Gwendal Roué 是 GRDB 的作者,這專案給了他觀察變化發生的處理許多經驗,他認為 SE-0395 有幾點沒考慮完善,給出了一篇很值得閱讀的長文。
他認為觀察的基本大兩原則為:以交易(transaction)為信號單位,和保持原始物件的 invariant (讀者們抱歉,這個詞我真不知道怎麼翻成中文)。實際上這和我以前寫 Reactive Programming 遇過的困難經驗相符,如果訊號單純只是所有 property 的變化流,很容易變成一場災難。因為修改資料方可能邏輯地做出多個改動,但是接收方完全很難逆推這些邏輯,判斷是否全都要回應處理也變得困難,在每個 transaction 結束時才發送通知很合理。
🤪 Pofat 選推
Twitter 無預警地限制了 Substack 的存取,目前推文預覽還是爛的,只好使出截圖大法!
我們水果信徒都是抖M,沒事
風口上很擠的啊
真理,不服來(跟 brain as service 哥)戰
各遊戲發行商,切記五月 12 那週不要自殺式發行啊,遊戲王者王國之淚即將降臨啊