WWDC26 What's New in SwiftUI
SwiftUI 今年沒有顛覆性新概念,但散落的小改動加起來很可觀。這篇整理 What’s New in SwiftUI session 的重點。
🎨 Liquid Glass 自動適配
升上 iOS 27 / macOS 27 後,App 不需要改 code 就會自動套用新的 Liquid Glass 外觀——前提是你沒有大量自製 UI。
幾個搭配的新環境值和行為:
@Environment(\.appearsActive):讓 inactive 視窗的內容可以變暗(自己控制透明度)- Menu bar 預設改顯示精簡 icon;要顯示文字加 icon,用
.labelStyle(.titleAndIcon) - iPhone App 在 iOS 27 變成可調整大小——Xcode 27 Live Preview 也有 resize handle 可以測試
🛠 Toolbar 強化
四個新東西,組合起來很實用:
| |
捲動時自動收起:
| |
以前要做這些效果都得自己土法煉鋼,現在系統內建。
📋 .reorderable() 與 .swipeActions() 通用化
過去這兩個 modifier 都只能用在 List 上,現在解放到任何容器。
Reorderable(拖曳排序)
| |
watchOS 也是第一次支援。SwiftUI 處理拖曳動畫和插入位置預覽,你只負責把 difference 套用回資料源。
Swipe Actions
| |
swipeActionsContainer() 加在 ScrollView 上,系統會自動處理「只能同時開一列」、「捲動關閉」這些行為。
🖼️ AsyncImage 升級
兩個一直以來的痛點終於解決。
自動 HTTP cache
| |
不改一行 code,就會遵循 server 的 cache header 做快取。以前要自己包一層 URLSession + URLCache,現在內建。
支援 URLRequest 和自訂 URLSession
| |
URLRequest 可以帶 header(authenticated endpoint)、客製 timeout 和 cache policy;asyncImageURLSession modifier 套用到整個 view hierarchy。
⚠️ @State 延遲初始化(會打到舊 code)
這次 SwiftUI 最重要的改動,而且會讓你既有專案編譯失敗。
改動
| |
效能改善很大,而且回填到 iOS 17、macOS 14 等舊版本。
Breaking change
| |
升版前先 grep 一下專案裡 init 中對 @State 的賦值,提早處理。詳見 TN3211。
🏗️ ContentBuilder
ViewBuilder 的進化版,多種 builder 統一成 ContentBuilder:
| |
對使用者最直接的影響是編譯速度——複雜 view hierarchy 在 Xcode 27 build 起來明顯比較快。不指定 deployment target 都能用。
📑 Document API 大改
WritableDocument / ReadableDocument 取代舊的 FileDocument,主要強化:
- Snapshot-based diffing:只寫變動的部分,效能提升
- 非同步、nonisolated 寫入:寫檔不卡 UI
- Subprogress 進度回報:搭配 Foundation 新 API
DocumentGroupLaunchScene:可以提供多種建立來源(blank、從照片、template…)
如果你有寫 document-based App,這次是值得重做的程度。
🎯 其他小改動
Prominent Tab role
| |
Confirmation dialog 支援 item binding
| |
跟 .sheet(item:) 寫法一致,比之前用 isPresented + 額外 state 乾淨很多。.alert() 也有同款 overload。
🔚 總結
這次 SwiftUI 沒有概念性的大轉折,但該補的洞補了不少:
- AsyncImage cache 跟 URLRequest 支援,少寫一層 wrapper
.reorderable()和.swipeActions()終於不限 List- @State 延遲初始化是性能 + 行為的正向改善,但升版前一定要先檢查 init
- Toolbar API 變強,動態 minimize 行為內建
最值得提早處理的是 @State init 賦值會編譯錯誤,其他都是無痛升級。
What’s New in SwiftUI — WWDC26 Session 269
本文使用 Claude 共同完成