SwiftUI 在 WWDC 24 之后的新變化
前言
WWDC 24 已經到來,我們有很多內容要討論。每年,SwiftUI 都會通過引入更多功能來趕上 UIKit。今年也不例外。讓我們深入了解 SwiftUI 框架引入的新功能。
我首先要提到的主要變化是 App、Scene 和 View 協議的 @MainActor 隔離。這可能會破壞你的代碼,所以請記住這一點。
視圖集合
SwiftUI 為 Group 和 ForEach 視圖引入了新的重載,允許我們創建自定義容器,如 List 或 TabView。
struct AppStoreView<Content: View>: View {
@ViewBuilder var content: Content
var body: some View {
VStack {
Group(subviewsOf: content) { subviews in
HStack {
if !subviews.isEmpty {
subviews[0]
}
if subviews.count > 1 {
subviews[1]
}
}
if subviews.count > 2 {
VStack {
subviews[2...]
}
}
}
}
}
}
如上例所示,我們使用帶有新初始化器的 Group 視圖,允許我們訪問通過 @ViewBuilder 閉包傳遞的內容視圖的子視圖。SwiftUI 引入了新的 Subview 和 SubviewsCollection 類型,提供了對真實視圖的代理訪問。
新的標簽欄體驗
使用新的 Tab 類型,SwiftUI 提供了新的可定制標簽欄體驗,帶有流暢過渡到側邊欄。
enum Destination: Hashable {
case home
case search
case settings
case trends
}
struct RootView: View {
@State private var selection: Destination = .home
var body: some View {
TabView {
Tab("home", systemImage: "home", value: .home) {
HomeView()
}
Tab("search", systemImage: "search", value: .search) {
SearchView()
}
TabSection("Other") {
Tab("trends", systemImage: "trends", value: .trends) {
TrendsView()
}
Tab("settings", systemImage: "settings", value: .settings) {
SettingsView()
}
}
.tabViewStyle(.sidebarAdaptable)
}
}
}
如上例所示,我們使用新的 Tab 類型來定義標簽。我們還在 TabSection 實例上使用 tabViewStyle 視圖修飾符,將特定的標簽部分分組并移動到側邊欄。
英雄動畫
SwiftUI 引入了 matchedTransitionSource 和 navigationTransition,我們可以在任何 NavigationLink 實例中配對使用。
struct HeroAnimationView: View {
@Namespace var hero
var body: some View {
NavigationStack {
NavigationLink {
DetailView()
.navigationTransition(.zoom(sourceID: "myId", in: hero))
} label: {
ThumbnailView()
}
.matchedTransitionSource(id: "myId", in: hero)
}
}
}
這使我們能夠在 NavigationStack 內從一個視圖導航到另一個視圖時,使用相同的標識符和命名空間創建平滑的過渡。
滾動位置
新的 ScrollPosition 類型與 scrollPosition 視圖修飾符配對,允許我們讀取 ScrollView 實例的精確位置。我們還可以使用它編程地滾動到滾動內容的特定點。
struct ScrollPositionExample: View {
@State private var position: ScrollPosition = .init(point: .zero)
var body: some View {
ScrollView {
ForEach(1..<1000) { item in
Text(item.formatted())
}
Button("jump to top") {
position = ScrollPosition(point: .zero)
}
}
.scrollPosition($position)
}
}
Entry 宏
新的 Entry 宏允許我們快速引入環境值、聚焦值、容器值等,無需樣板代碼。讓我們看看在 Entry 宏之前我們如何定義環境值。
struct ItemsPerPageKey: EnvironmentKey {
static var defaultValue: Int = 10
}
extension EnvironmentValues {
var itemsPerPage: Int {
get { self[ItemsPerPageKey.self] }
set { self[ItemsPerPageKey.self] = newValue }
}
}
現在,我們可以通過使用 Entry 宏來簡化代碼。
extension EnvironmentValues {
@Entry var itemsPerPage: Int = 10
}
預覽
新的 Previewable 宏允許我們在預覽中引入狀態,而無需將其包裝到額外的包裝視圖中。
#Preview("toggle") {
@Previewable @State var toggled = true
return Toggle("Loud Noises", isOn: $toggled)
}
其他
SwiftUI 框架的下一版本包括許多新 API,如窗口推送、TextField 和 TextEditor 視圖中的文本選擇觀察、搜索焦點監控、自定義文本渲染、新的 MeshGradient 類型等等,我無法在一篇文章中涵蓋所有內容。
總結
在 WWDC 24 上,SwiftUI 再次通過引入更多新功能來提升其成熟度,以趕上 UIKit。今年的主要變化包括 @MainActor 隔離、視圖集合的新重載、新的可定制標簽欄體驗、英雄動畫、滾動位置的新功能以及新的 Entry 和 Previewable 宏。這些改進使開發者能夠創建更靈活和高效的用戶界面。SwiftUI還引入了許多新的API,如窗口推送、文本選擇觀察、搜索焦點監控等,使開發更加便捷和強大。