SwiftUI 在 WWDC 24 之后的新變化
前言
WWDC 24 已經(jīng)到來,我們有很多內(nèi)容要討論。每年,SwiftUI 都會通過引入更多功能來趕上 UIKit。今年也不例外。讓我們深入了解 SwiftUI 框架引入的新功能。
我首先要提到的主要變化是 App、Scene 和 View 協(xié)議的 @MainActor 隔離。這可能會破壞你的代碼,所以請記住這一點(diǎn)。
視圖集合
SwiftUI 為 Group 和 ForEach 視圖引入了新的重載,允許我們創(chuàng)建自定義容器,如 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 閉包傳遞的內(nèi)容視圖的子視圖。SwiftUI 引入了新的 Subview 和 SubviewsCollection 類型,提供了對真實(shí)視圖的代理訪問。
新的標(biāo)簽欄體驗(yàn)
使用新的 Tab 類型,SwiftUI 提供了新的可定制標(biāo)簽欄體驗(yàn),帶有流暢過渡到側(cè)邊欄。
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 類型來定義標(biāo)簽。我們還在 TabSection 實(shí)例上使用 tabViewStyle 視圖修飾符,將特定的標(biāo)簽部分分組并移動到側(cè)邊欄。
英雄動畫
SwiftUI 引入了 matchedTransitionSource 和 navigationTransition,我們可以在任何 NavigationLink 實(shí)例中配對使用。
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 內(nèi)從一個視圖導(dǎo)航到另一個視圖時,使用相同的標(biāo)識符和命名空間創(chuàng)建平滑的過渡。
滾動位置
新的 ScrollPosition 類型與 scrollPosition 視圖修飾符配對,允許我們讀取 ScrollView 實(shí)例的精確位置。我們還可以使用它編程地滾動到滾動內(nèi)容的特定點(diǎn)。
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 宏允許我們快速引入環(huán)境值、聚焦值、容器值等,無需樣板代碼。讓我們看看在 Entry 宏之前我們?nèi)绾味x環(huán)境值。
struct ItemsPerPageKey: EnvironmentKey {
static var defaultValue: Int = 10
}
extension EnvironmentValues {
var itemsPerPage: Int {
get { self[ItemsPerPageKey.self] }
set { self[ItemsPerPageKey.self] = newValue }
}
}
現(xiàn)在,我們可以通過使用 Entry 宏來簡化代碼。
extension EnvironmentValues {
@Entry var itemsPerPage: Int = 10
}
預(yù)覽
新的 Previewable 宏允許我們在預(yù)覽中引入狀態(tài),而無需將其包裝到額外的包裝視圖中。
#Preview("toggle") {
@Previewable @State var toggled = true
return Toggle("Loud Noises", isOn: $toggled)
}
其他
SwiftUI 框架的下一版本包括許多新 API,如窗口推送、TextField 和 TextEditor 視圖中的文本選擇觀察、搜索焦點(diǎn)監(jiān)控、自定義文本渲染、新的 MeshGradient 類型等等,我無法在一篇文章中涵蓋所有內(nèi)容。
總結(jié)
在 WWDC 24 上,SwiftUI 再次通過引入更多新功能來提升其成熟度,以趕上 UIKit。今年的主要變化包括 @MainActor 隔離、視圖集合的新重載、新的可定制標(biāo)簽欄體驗(yàn)、英雄動畫、滾動位置的新功能以及新的 Entry 和 Previewable 宏。這些改進(jìn)使開發(fā)者能夠創(chuàng)建更靈活和高效的用戶界面。SwiftUI還引入了許多新的API,如窗口推送、文本選擇觀察、搜索焦點(diǎn)監(jiān)控等,使開發(fā)更加便捷和強(qiáng)大。