close

編譯 | 核子可樂、Tina
SwiftUI 很好,但是蘋果對它投資不足。

在 2019 年的 WWDC 大會上,蘋果推出了一個全新的 SwiftUI 框架,這是一個現代化的 UI 界面編碼結構,它是基於 Swift從頭開始構建的。新框架使用聲明性範例,讓開發者用更少的代碼編寫相同的 UI。

SwiftUI 的願景是降低開發 iOS 門檻,吸引更多開發者、豐富 iOS 的業態。並且 SwiftUI 可以「實現一次編碼,可適應五端 Apple 產品平台」, 包括watchOS、tvOS、macOS 等,以此統一蘋果平台的 UI 框架。

蘋果傳遞出來的消息就像是說:「SwiftUI 是一個了不起的用戶界面框架,而且 100% 絕對會成為蘋果平台上應用開發的未來。」

這些年,也有一些用 SwiftUI 重寫 UIKit 應用程序的案例,去年奈飛新版 iOS App 的登錄界面也完全由 SwiftUI 重構。

本文的作者 chsxf,是一家獨立遊戲工作室的首席開發,也是 15 年的蘋果用戶,他想嘗試將 SwiftUI 放到自己的項目中,但是最終失敗了。他發表了一篇博客,總結了嘗試並放棄 SwiftUI 的過程,這篇文章在 Hacker News 上引發了開發者們的大量討論:

「恕我直言,SwiftUI 是一個很好的機會,但蘋果公司對它投資不足。這是一項很好的技術,響應式方法非常適合許多典型的基於視圖的需求,但對如何處理邊緣情況,文檔中非常缺乏相關的說明。」

「這是個好主意,但 SwiftUI 的主要問題是完全不成熟。」「它具有複雜的行為,不適用於需要大容量或複雜 UI 的 App。」

「而且 SwiftUI 改進太慢了。」

..........

chsxf 的博客原文翻譯:

最近,我手頭正好有個「The Untitled Project」(名字還沒想好)項目需要完成。考慮到配套創作工具 CiderKit 在發展成熟的過程中也變得愈發複雜,再加上創建各種窗口和 UI 元素的實際需求,我決定嘗試用用 SwiftUI。這是個寶貴的機會,能讓我認真體驗一把 SwiftUI 並探索其內部工作原理。

起初項目工作良好,我對 SwiftUI 的表現可以說非常滿意,我甚至創建了自己的修改器,以便更輕鬆地顯示警報消息。但美好的甜蜜期很快過去,接下來我就要說道說道 SwiftUI 的那些「壞毛病」了。

實時檢查器不好用

接下來,我開始了 SwiftUI 探索之旅的第二站——為地圖編輯器創建實時檢查器。跟其他創作工具一樣,這款檢查器的功能就是選定一個對象,並把可檢查的對應屬性顯示在一個臨時的用戶界面元素當中。過程當中,Swift 協議和它處理泛型的方式也給我帶來了不少麻煩,但這裡我們就不過多展開了。

我還遇到了其他問題,因為 SwiftUI 高度依賴於 View 協議的實現結構,但 View 協議又有關聯的類型,所以只能把它當成約束來用。好在配合 some 關鍵字和 opaque 類型等設計,我最終還是為可選對象找到了一種實現方法,讓每個對象都能提供自身特定的 UI 元素。

之所以下決心選擇 SwiftUI,就是因為初步測試時效果不錯。如上圖所示,地圖編輯器位於左側,檢查器位於右側。起初,我測試了一個 UI 元素,那是個用於開燈和關燈的勾選框。它運行良好,所以我根本想象不到後續會出什麼大亂子。

但在開始實現更複雜的檢查器視圖時,特別是涉及帶有 / 不帶步進器或顏色選擇器的多個文本字段時,整個運行速度開始劇烈下降。SpriteKit 視圖一般都能以每秒 60 幀的完美速率呈現(只要用的不是英特爾孱弱的 iGPU)。但每當 SwiftUI 更新檢查器視圖時(這種更新可能出現在移動過程中,甚至是在輸入文本字段的時候),渲染速率都會下降到每秒 10 到 15 幀,而且相當不穩定。這顯然讓人無法容忍。

我認真做了一番分析,並發現了幾個問題。首先,由可選對象提供的視圖在每次重繪時都是在完全重新創建。我雖然通過緩存稍稍提升了性能表現,但實際體驗仍然非常糟糕。事實證明,SwiftUI 檢查器視圖就是沒法提供合理的重繪速度。我在網上查找了解決方案,最後編寫了一個延遲版本的 ObservableObject,由它來強制每秒只發布一次更改(參見以下代碼)。

import Combineimport Foundationextension ObservableObject { func delayed(_ delay: TimeInterval = 1.0) -> DelayedObservableObject<Self> { return .init(object: self, delay: delay) }}@dynamicMemberLookupclass DelayedObservableObject<Object>: ObservableObject where Object: ObservableObject { private var original: Object private var subscription: AnyCancellable? fileprivate init(object: Object, delay: TimeInterval) { self.original = object subscription = object.objectWillChange .throttle(for: RunLoop.SchedulerTimeType.Stride(delay), scheduler: RunLoop.main, latest: true) .sink { [weak self] _ in self?.objectWillChange.send() } } subscript<Subject>(dynamicMember keyPath: WritableKeyPath<Object, Subject>) -> Subject { get { original[keyPath: keyPath] } set { original[keyPath: keyPath] = newValue } }}

隨着重繪頻率的降低,終於能比較順暢地操作地圖上的對象了,每秒的幀率浮動一般就只有個位數。但這會導致檢查器中的值出現延遲,因此在地圖編輯器的交互過程中(比如使用移動工具時)結果不準確,所以效果還是稱不上完美。

但我覺得這可能只是個獨立問題,並不能因此把 SwiftUI 一棒子打死。所以,我打算繼續探索。

越來越慢

在實現了第一個檢查器之後,我開始研究另一個主題:Sprite 資產編輯器。利用這款工具,我可以用多個 sprite 拼接成複雜的資產,再最終為它們製作動畫。它的顯示效果就是主窗口中的一張表,出於學習的目的,我當然還是想繼續用 SwiftUI 嘍。畢竟初次嘗試肯定會有種種問題,應該再給它一次機會。

如大家所見,這是個複雜的窗口,包含多種不同上下文(上方的「Sprite 資產數據庫」列表,左側的特定「Sprite 資產數據庫」內容,以及其他與選定 Sprite 資產對應的編輯器元素)。我需要為每個上下文創建一個視圖,這些視圖同時又是其他視圖的「子視圖」,然後把需要的數據傳遞給特定視圖。

但上圖展示的效果其實是在 AppKit 中完成的,因為我在 SwiftUI 一直實現不了預期的功能。大家應該注意到了,中間的 SpriteKit 視圖上有三個按鈕(分別是 +、200% 和 -)。這些按鈕只跟管理 SpriteKit 視圖縮放的 @State 相關聯。儘管幾乎不涉及任何其他數據,在界面更新前單擊這些按鈕,也會產生將近一秒鐘的巨大延遲。我剛開始以為是因為地圖編輯器的 SpriteKit 主視圖仍在後台渲染。所以我嘗試在工作表顯示出來後禁用渲染,但結果沒有任何改變。

變更從一種環境傳播至另一環境時,我也遇到了類似的延遲問題。這可以說是壓死駱駝的最後一根稻草了,我決定放棄 SwiftUI,繼續用 AppKit。

總 結

其實沒能在項目中用到 SwiftUI,會讓我感覺有點遺憾。我仍然覺得它是一項很棒的技術,只是可能不適合我的這個特定用例。但我真的不確定是不是自己的用法有問題。我打算在 Nihongo no Kana 的更新版本中再用用 SwiftUI,畢竟那款 iOS/iPadOS 應用的重繪頻率低得多,所以應該不會有太大問題。

也許 SwiftUI 還沒做好全面替代 AppKit 的準備。The Untitled Project 的 CiderKit 創作工具並不是作為 Catalyst 應用構建的,也不依賴於 UIKit。但繼續使用 AppKit 的最大優點,就是沒有任何延遲而且一切功能完全符合預期。當然,整個構建過程更繁瑣,而且自動布局功能也不怎麼好用。但我至少可以更好地控制應用程序的行為,而且根據需求隨意調整各種元素。

總之,經歷了這麼一番波折,我還是很慶幸自己果斷放棄了 SwiftUI。這可能是我在這個項目上做過的最明智的選擇。

參考鏈接:

https://chsxf.dev/2022/08/28/5-tup-why-i-quit-using-swiftui.html

https://news.ycombinator.com/itemid=32630389

https://xie.infoq.cn/article/28af907f31baa7e7283a31ed4

今日好文推薦

英偉達回應「對中國斷供部分高端 GPU」;月薪 3.6 萬工程師日均寫 7 行代碼被開;12 年黑進 40 多家金融機構老闆賺百萬獲刑 |Q 資訊

在阿里達摩院搞了四年數據庫,我來聊聊實際情況 | 卓越技術團隊訪談錄

30 年 IT 老兵談數字化:這就不是個技術活

資深 Web 開發的經驗之談:為什麼你開發的網頁不應該大於 14KB?

課程推薦

前阿里 P10 、浙江大學博導東白老師在極客時間出個專欄,叫《郭東白的架構課》,非常火爆,已經有超過 2w 人學習了。

這個專欄共 67 講,約 35w 字,內容包括「架構師的六大生存法則、架構師的價值創造、程序員職業成長、程序員思考力提升」四個模塊,適合架構師學習,更適合未來想成為架構師的朋友學習。

專欄過兩天就漲價到 ¥199 了,極客時間新用戶限時 ¥59,推薦入手!

👇長按掃碼,可免費試讀👇

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()