SwiftUI 七年後:平庸的故事
在 2019 年發布七年後,SwiftUI 的初衷是成為 Apple 平台跨平台 UI 開發中成熟且具備生產等級的未來。然而,許多資深工程師現在將其視為一個處於永久 Beta 狀態的框架,以精確的工程設計換取了便利性的幻象。
不可預測的數據流與響應性
SwiftUI 的數據流被描述為一個「黑盒」,要實現可預測的行為幾乎是不可能的。雖然「單一事實來源」的概念在理論上很有吸引力,但其實際實現已演變成一組令人困惑的屬性包裝器(property wrappers)和宏(macros)。
- 狀態管理的演進: 該框架始於
@State、@Binding和ObservedObject。由於性能問題和過度的重新渲染,Apple 引入了 Observation framework 和@Observable宏。 - 缺乏透明度: 開發者報告稱,即使使用像
Self._printChanges()這樣未公開的調試 API,也往往無法確切知道一個視圖(view)會更新多少次,或者為什麼會觸發特定的更新。
佈局引擎的脆弱性與 GeometryReader 陷阱
SwiftUI 的佈局系統基於尺寸協商(size negotiation),常被描述為不可預測且脆弱,特別是在構建複雜界面,如自定義側邊欄或懸浮視圖時。
- 佈局不一致性: 即使是 Apple 官方的教學文件,也被指出在最新的 macOS 版本上運行時會出現佈局錯誤。
- The GeometryReader Workaround: 當聲明式系統失效時,開發者通常會求助於
GeometryReader來手動計算座標。這被視為一種「認輸」的行為,因為它消除了聲明式的優勢,並增加了比傳統 Auto Layout 系統更高的冗餘度。
API 不穩定性與功能對等差距
SwiftUI 在與 UIKit 和 AppKit 等傳統框架的功能對等性方面持續掙扎。這導致代碼庫中充斥著為了維持向後兼容性而進行的 if #available 檢查。
- 延遲的功能實現: 儘管基本功能在傳統框架中已存在數十年,但像是在滾動時隱藏鍵盤(iOS 16)或透過
AsyncImage顯示網絡圖像(iOS 15)等功能,在 SwiftUI 中花費了數年才實現。 - 組件替換: Apple 有時會直接替換掉有 Bug 的組件,而不是修復它們(例如,將
NavigationView替換為NavigationStack),這迫使開發者必須為不同的 OS 版本維護獨立的代碼分支。 - 緩存限制: 截至 2026 年 7 月,某些用於圖像緩存的關鍵 API 仍處於 Beta 階段,迫使開發者必須構建自定義的獲取器和緩存層。
性能差異
正面對比顯示,SwiftUI 的性能通常落後於 UIKit,特別是在數據密集型視圖中。
- 滾動性能: 即使在高端硬體上,SwiftUI 中簡單的圖像畫廊和大型網格也往往感覺不如 UIKit 的對應版本流暢。
- 優化開銷: 實現可接受的性能通常需要使用晦澀的優化技巧,這與該框架承諾的簡潔性相矛盾。
「學一次,到處應用」的迷思
雖然 Apple 將 SwiftUI 行銷為一種「學會這些工具一次,然後到處應用」的方式,但現實是,6 英寸的手機與 27 英寸的桌面電腦的 UI 設計有著根本的不同。
- 平台差異: 在 iOS 上學到的概念很少能直接應用於 macOS 佈局,否則會導致「異物感」強烈的 UI,感覺像是移植的 iPad App。
- 實現不一致性: 同樣的視圖在不同的 Apple 平台上有時會有不一致的實現,導致開發者陷入沉重的調試工作流:「學一次,學兩次,應用在某處,調試到處都是」。
向「足夠好」的哲學轉變
人們越來越擔心,SwiftUI 代表了 Apple 從不妥協的工藝精神轉向一種追求「速度」與「足夠好」產品的文化。
Bug 的常態化: 這種轉變可以從官方 App 的持續性 Bug 中得到證實(例如:Apple Music 隊列跳轉、重複的 Home Screen 圖標,以及 Logic Pro 中缺失的 localization)。
與傳統時代的對比: 這與最初的 Cocoa 和 Aqua 時代形成對比,那時期的視覺瑕疵和不穩定性會被認為是不可接受的的。
社群觀點與反論
開發者討論揭示了那些將 SwiftUI 視為失敗與那些將其視為強大(儘管不完美)工具之間的分歧。
"SwiftUI is the type of framework that makes the easy things easier to accomplish but the harder things harder. It is a newbie trap."
"I’ve been using SwiftUI without major performance issues... I profile and fix as needed. One of the early studios I worked for wrote all our games in UIKit as prototypes... when performance tanked we’d switch to the appropriate tools."
"For 90% of work, SwiftUI is good but for the 10% you would need AppKit. For my app... I needed to load and show a large number of chat items in a list, SwiftUI is really bad at this."
一些開發者認為,挫折感源於「UIKit 持有者」的心態,並認為對於簡單的 App,SwiftUI 的生產力明顯高於傳統框架那種冗長的樣板代碼(boilerplate)性質。