SwiftUI 是 Apple 于 2019 年 WWDC 上发布的新 UI 框架,它简化了界面开发,使得开发者可以使用声明式语法构建用户界面。在 SwiftUI 中,属性包装器(Property Wrappers)是一个非常重要的概念,它们被用来管理视图状态和数据绑定。本文将详细介绍 SwiftUI 中常用的属性包装器,包括 @AppStorage
、@Binding
、@EnvironmentObject
、@FocusedBinding
、@GestureState
、@Namespace
、@ObservedObject
、ObservableObject
、@SceneStorage
、@State
、@StateObject
以及 @UIApplicationDelegateAdaptor
。本文不仅会解释每个属性包装器的作用和原理,还会给出具体的使用示例,并探讨它们之间的区别和注意事项。
@State
作用和原理
@State
是 SwiftUI 中最基础的属性包装器之一,它用来声明视图的局部状态。通过使用 @State
,SwiftUI 可以在状态变化时自动重新渲染视图。
示例
import SwiftUI
struct CounterView: View {
@State private var count = 0
var body: some View {
VStack {
Text("Count: \(count)")
Button(action: {
count += 1
}) {
Text("Increment")
}
}
}
}
注意事项
@State
属性只能在结构体(struct)类型中使用。- 只能在视图的局部范围内使用,不应传递到子视图中使用。
@Binding
作用和原理
@Binding
用于在不同视图之间共享和同步状态。它通常用于子视图与父视图之间的状态传递,使得子视图可以修改父视图的状态。
示例
import SwiftUI
struct ParentView: View {
@State private var isOn = false
var body: some View {
ToggleView(isOn: $isOn)
}
}
struct ToggleView: View {
@Binding var isOn: Bool
var body: some View {
Toggle("Toggle", isOn: $isOn)
}
}
注意事项
@Binding
属性必须从其他地方传入绑定的值,通常是父视图。@Binding
不持有数据,只是一个引用,不能独立存在。
@ObservedObject 和 ObservableObject
作用和原理
@ObservedObject
和 ObservableObject
用于管理复杂的数据和状态,并在数据发生变化时通知视图更新。
示例
import SwiftUI
import Combine
class TimerModel: ObservableObject {
@Published var counter = 0
private var timer: Timer?
func start() {
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
self.counter += 1
}
}
func stop() {
timer?.invalidate()
timer = nil
}
}
struct TimerView: View {
@ObservedObject var model = TimerModel()
var body: some View {
VStack {
Text("Counter: \(model.counter)")
Button("Start") {
model.start()
}
Button("Stop") {
model.stop()
}
}
}
}
注意事项
ObservableObject
类的属性需要使用@Published
修饰,这样属性的变化才能被视图检测到。@ObservedObject
可以在多个视图中使用,但不会管理其生命周期。
@StateObject
作用和原理
@StateObject
是 SwiftUI 2.0 引入的一个新属性包装器,用于创建和管理 ObservableObject
的生命周期。与 @ObservedObject
不同,@StateObject
只应在对象的初始化时使用一次。
示例
import SwiftUI
class CounterModel: ObservableObject {
@Published var count = 0
func increment() {
count += 1
}
}
struct CounterStateObjectView: View {
@StateObject private var model = CounterModel()
var body: some View {
VStack {
Text("Count: \(model.count)")
Button("Increment") {
model.increment()
}
}
}
}
注意事项
@StateObject
应该在视图的初始化时使用,只使用一次。- 在视图的更新过程中,
@StateObject
保证对象实例不会被重新创建。
@EnvironmentObject
作用和原理
@EnvironmentObject
用于在视图层次结构中共享数据。它类似于依赖注入,可以让多个视图访问相同的数据对象。
示例
import SwiftUI
class UserSettings: ObservableObject {
@Published var username: String = "Guest"
}
struct ProfileView: View {
@EnvironmentObject var settings: UserSettings
var body: some View {
Text("Username: \(settings.username)")
}
}
struct ContentView: View {
var body: some View {
ProfileView().environmentObject(UserSettings())
}
}
注意事项
@EnvironmentObject
依赖于 SwiftUI 环境中的对象,需要使用.environmentObject()
在父视图中注入。- 使用
@EnvironmentObject
的视图必须在视图层次结构中能够访问到注入的对象,否则会导致运行时错误。
@AppStorage
作用和原理
@AppStorage
用于将视图的状态与 UserDefaults
绑定,从而实现数据的持久化存储。
示例
import SwiftUI
struct SettingsView: View {
@AppStorage("username") private var username: String = "Guest"
var body: some View {
VStack {
TextField("Username", text: $username)
Text("Stored Username: \(username)")
}
.padding()
}
}
注意事项
@AppStorage
只能存储基本的数据类型(如String
、Int
、Bool
等)。- 数据存储在
UserDefaults
中,所以需要确保存储的数据量较小。
@SceneStorage
作用和原理
@SceneStorage
用于在多个应用场景中存储数据。当应用场景发生变化时(例如在 iPad 上的多窗口环境),@SceneStorage
可以保留数据。
示例
import SwiftUI
struct SceneStorageView: View {
@SceneStorage("note") private var note: String = ""
var body: some View {
TextEditor(text: $note)
.padding()
}
}
注意事项
@SceneStorage
主要用于在 iPad 的多窗口环境中保留数据。- 类似于
@AppStorage
,但专注于场景特定的数据存储。
@FocusedBinding
作用和原理
@FocusedBinding
用于在当前焦点上下文中绑定数据,通常用于处理键盘焦点和输入。
示例
import SwiftUI
struct FocusedBindingView: View {
@FocusState private var isTextFieldFocused: Bool
var body: some View {
TextField("Enter text", text: .constant(""))
.focused($isTextFieldFocused)
.padding()
}
}
注意事项
@FocusedBinding
需要与@FocusState
结合使用。- 用于处理视图中的焦点状态,通常用于表单输入和键盘管理。
@GestureState
作用和原理
@GestureState
用于跟踪手势状态变化,适用于手势识别和处理。
示例
import SwiftUI
struct GestureStateView: View {
@GestureState private var isDragging = false
var body: some View {
Circle()
.fill(isDragging ? Color.green : Color.blue)
.frame(width: 100, height: 100)
.gesture(
DragGesture()
.updating($isDragging) { value, state, transaction in
state = true
}
)
}
}
注意事项
@GestureState
用于在手势过程中跟踪状态,手势结束后状态会自动重置。- 适用于复杂的手势处理和动画效果。
@Namespace
作用和原理
@Namespace
用于定义 SwiftUI 的动画命名空间,常用于视图过渡和匹配动画。
示例
import SwiftUI
struct NamespaceView: View {
@Namespace private var animation
@State private var isExpanded = false
var body: some View {
VStack {
if isExpanded {
RoundedRectangle(cornerRadius: 25.0)
.matchedGeometryEffect(id: "shape", in: animation)
.frame(width: 300, height: 200)
} else {
RoundedRectangle(cornerRadius: 25.0)
.matchedGeometryEffect(id: "shape", in: animation)
.frame(width: 100, height:
100)
}
}
.onTapGesture {
withAnimation {
isExpanded.toggle()
}
}
}
}
注意事项
@Namespace
用于动画过渡,需要与matchedGeometryEffect
一起使用。@Namespace
声明的命名空间可以在多个视图之间共享。
@UIApplicationDelegateAdaptor
作用和原理
@UIApplicationDelegateAdaptor
用于将自定义的 UIApplicationDelegate
实现注入到 SwiftUI 的 App
生命周期中。
示例
import SwiftUI
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Custom setup
return true
}
}
@main
struct MyApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
注意事项
@UIApplicationDelegateAdaptor
主要用于需要自定义UIApplicationDelegate
行为的场景。- 在 SwiftUI 中使用传统的
AppDelegate
方法时非常有用。
@Environment
作用和原理
@Environment
用于读取 SwiftUI 环境中的值。SwiftUI 环境是一个动态属性集合,可以传递应用中的共享数据,比如颜色方案、尺寸类别等。
示例
import SwiftUI
struct EnvironmentView: View {
@Environment(\.colorScheme) var colorScheme
var body: some View {
Text("Current color scheme: \(colorScheme == .dark ? "Dark" : "Light")")
.padding()
}
}
注意事项
@Environment
属性只能读取环境中的值,不能修改它们。- 要将值注入到环境中,可以使用
.environment()
修饰符。
@Environment(.managedObjectContext)
作用和原理
@Environment(\.managedObjectContext)
是 Core Data 的特定环境值,用于将 NSManagedObjectContext
注入到 SwiftUI 视图中。
示例
import SwiftUI
import CoreData
struct CoreDataView: View {
@Environment(\.managedObjectContext) private var viewContext
var body: some View {
Button("Add Item") {
let newItem = Item(context: viewContext)
newItem.timestamp = Date()
do {
try viewContext.save()
} catch {
// Handle error
}
}
}
}
注意事项
- 使用 Core Data 时,需要在应用的入口视图中将
NSManagedObjectContext
注入环境中。
@FetchRequest
作用和原理
@FetchRequest
是用于从 Core Data 中获取数据的属性包装器。它会自动执行指定的 fetch 请求,并在数据更改时更新视图。
示例
import SwiftUI
import CoreData
struct FetchRequestView: View {
@FetchRequest(
entity: Item.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)]
) var items: FetchedResults<Item>
var body: some View {
List(items) { item in
Text("Item at \(item.timestamp!, formatter: dateFormatter)")
}
}
}
注意事项
@FetchRequest
只能在视图中使用,用于自动管理 Core Data 数据的获取和更新。- 需要确保数据模型和 fetch 请求正确配置。
@ScaledMetric
作用和原理
@ScaledMetric
用于根据用户的动态类型设置调整字体大小等视图尺寸。它可以确保视图在不同的字体设置下具有良好的可读性和一致性。
示例
import SwiftUI
struct ScaledMetricView: View {
@ScaledMetric var fontSize: CGFloat = 20
var body: some View {
Text("Hello, World!")
.font(.system(size: fontSize))
.padding()
}
}
注意事项
@ScaledMetric
适用于需要根据用户设置动态调整尺寸的视图。- 确保使用
@ScaledMetric
属性包装器时设置合适的默认值。
@UIApplicationDelegateAdaptor
作用和原理
@UIApplicationDelegateAdaptor
用于将自定义的 UIApplicationDelegate
实现注入到 SwiftUI 的 App
生命周期中。
示例
import SwiftUI
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Custom setup
return true
}
}
@main
struct MyApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
注意事项
@UIApplicationDelegateAdaptor
主要用于需要自定义UIApplicationDelegate
行为的场景。- 在 SwiftUI 中使用传统的
AppDelegate
方法时非常有用。
@Environment(.presentationMode)
作用和原理
@Environment(\.presentationMode)
用于控制视图的显示和隐藏状态,通常用于模态视图的关闭操作。
示例
import SwiftUI
struct PresentationModeView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
Button("Dismiss") {
presentationMode.wrappedValue.dismiss()
}
.padding()
}
}
注意事项
@Environment(\.presentationMode)
只能用于控制当前视图的显示和隐藏。- 确保在需要控制视图显示状态的地方正确使用。
@FocusState
作用和原理
@FocusState
用于管理视图中的焦点状态,通常用于处理文本输入焦点。
示例
import SwiftUI
struct FocusStateView: View {
@FocusState private var isFocused: Bool
var body: some View {
TextField("Enter text", text: .constant(""))
.focused($isFocused)
.padding()
Button("Toggle Focus") {
isFocused.toggle()
}
}
}
注意事项
@FocusState
用于管理输入焦点状态,需要与focused
修饰符一起使用。- 适用于表单输入和焦点管理。
@Environment(.locale)
作用和原理
@Environment(\.locale)
用于读取当前视图环境中的 Locale
对象。Locale
包含了应用的语言和地区设置。
示例
import SwiftUI
struct LocaleView: View {
@Environment(\.locale) var locale
var body: some View {
Text("Current locale: \(locale.identifier)")
.padding()
}
}
注意事项
@Environment(\.locale)
只能读取环境中的Locale
值,不能直接修改它们。- 要改变应用的
Locale
,需要在应用设置中进行调整。
@Environment(.calendar)
作用和原理
@Environment(\.calendar)
用于读取当前视图环境中的 Calendar
对象。Calendar
包含了应用的日历设置。
示例
import SwiftUI
struct CalendarView: View {
@Environment(\.calendar) var calendar
var body: some View {
Text("Current calendar: \(calendar.identifier)")
.padding()
}
}
注意事项
@Environment(\.calendar)
只能读取环境中的Calendar
值,不能直接修改它们。- 通常用于显示和处理日期相关的数据。
@Environment(.timeZone)
作用和原理
@Environment(\.timeZone)
用于读取当前视图环境中的 TimeZone
对象。TimeZone
包含了应用的时区设置。
示例
import SwiftUI
struct TimeZoneView: View {
@Environment(\.timeZone) var timeZone
var body: some View {
Text("Current time zone: \(timeZone.identifier)")
.padding()
}
}
注意事项
@Environment(\.timeZone)
只能读取环境中的TimeZone
值,不能直接修改它们。- 用于处理与时区相关的数据。
@ScaledMetric
作用和原理
@ScaledMetric
用于根据用户的动态类型设置调整字体大小等视图尺寸。它可以确保视图在不同的字体设置下具有良好的可读性和一致性。
示例
import SwiftUI
struct ScaledMetricView: View {
@ScaledMetric var fontSize: CGFloat = 20
var body: some View {
Text("Hello, World!")
.font(.system(size: fontSize))
.padding()
}
}
注意事项
@ScaledMetric
适用于需要根据用户设置动态调整尺寸的视图。- 确保使用
@ScaledMetric
属性包装器时设置合适的默认值。
@Environment(.accessibilityEnabled)
作用和原理
@Environment(\.accessibilityEnabled)
用于读取当前视图环境中的无障碍设置,检查无障碍功能是否启用。
示例
import SwiftUI
struct AccessibilityEnabledView: View {
@Environment(\.accessibilityEnabled) var accessibilityEnabled
var body: some View {
Text("Accessibility is \(accessibilityEnabled ? "enabled" : "disabled")")
.padding()
}
}
注意事项
@Environment(\.accessibilityEnabled)
只能读取环境中的无障碍设置值,不能直接修改它们。- 用于调整视图的行为和外观以适应无障碍要求。
@Environment(.dismiss)
作用和原理
@Environment(\.dismiss)
用于获取一个操作,用来关闭当前的视图。通常用于模态视图和导航视图的关闭操作。
示例
import SwiftUI
struct DismissView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
Button("Dismiss") {
dismiss()
}
.padding()
}
}
注意事项
@Environment(\.dismiss)
只能用于关闭当前显示的视图。- 确保在需要控制视图关闭的地方正确使用。
@ObservedResults
作用和原理
@ObservedResults
用于观察和管理从 Realm 数据库中获取的数据。在数据更改时,自动更新视图。
示例
import SwiftUI
import RealmSwift
class Task: Object, ObjectKeyIdentifiable {
@Persisted(primaryKey: true) var id: ObjectId
@Persisted var name: String = ""
@Persisted var isCompleted: Bool = false
}
struct TaskListView: View {
@ObservedResults(Task.self) var tasks
var body: some View {
List {
ForEach(tasks) { task in
Text(task.name)
}
}
}
}
注意事项
@ObservedResults
只能用于从 Realm 数据库中获取数据。- 需要确保 Realm 数据库和模型类正确配置。
@Query
作用和原理
@Query
是用于 Firestore 的 SwiftUI 属性包装器。它可以自动查询 Firestore 数据,并在数据变化时更新视图。
示例
import SwiftUI
import FirebaseFirestoreSwift
struct User: Identifiable, Codable {
@DocumentID var id: String?
var name: String
}
struct UsersView: View {
@Query(collectionPath: "users") var users: [User]
var body: some View {
List(users) { user in
Text(user.name)
}
}
}
注意事项
@Query
只能用于 Firestore 数据库。- 需要确保 Firestore 和模型类正确配置。
@ViewBuilder
作用和原理
@ViewBuilder
并不是一个属性包装器,而是一种结果构建器,它用于简化和增强视图构建器的声明。它允许你在单个视图构建器中返回多个视图。
示例
import SwiftUI
struct ViewBuilderExample: View {
var body: some View {
VStack {
content
}
}
@ViewBuilder
var content: some View {
Text("Hello, World!")
Text("This is another text")
}
}
注意事项
@ViewBuilder
主要用于简化视图构建器的代码,特别是在返回多个视图的情况下。- 只能用于视图构建器函数中。
@ObservedRealmObject
作用和原理
@ObservedRealmObject
用于观察和管理来自 Realm 数据库的对象。在数据更改时自动更新视图。
示例
import SwiftUI
import RealmSwift
class Task: Object, ObjectKeyIdentifiable {
@Persisted(primaryKey: true) var id: ObjectId
@Persisted var name: String = ""
@Persisted var isCompleted: Bool = false
}
struct TaskDetailView: View {
@ObservedRealmObject var task: Task
var body: some View {
VStack {
TextField("Task Name", text: $task.name)
Toggle("Completed", isOn: $task.isCompleted)
}
.padding()
}
}
注意事项
@ObservedRealmObject
只能用于从 Realm 数据库中获取数据。- 需要确保 Realm 数据库和模型类正确配置。
@PreferenceKey
作用和原理
@PreferenceKey
用于定义和读取视图层次结构中的自定义首选项值。它允许在父视图和子视图之间传递数据。
示例
import SwiftUI
struct PreferenceKeyExample: View {
var body: some View {
VStack {
Text("Hello, World!")
.anchorPreference(key: BoundsPreferenceKey.self, value: .bounds) { $0 }
}
.overlayPreferenceValue(BoundsPreferenceKey.self) { preferences in
GeometryReader { geometry in
if let bounds = preferences.first {
Rectangle()
.stroke()
.frame(width: bounds.width, height: bounds.height)
.offset(x: bounds.minX, y: bounds.minY)
}
}
}
}
}
struct BoundsPreferenceKey: PreferenceKey {
static var defaultValue: [Anchor<CGRect>] = []
static func reduce(value: inout [Anchor<CGRect>], nextValue: () -> [Anchor<CGRect>]) {
value.append(contentsOf: nextValue())
}
}
注意事项
@PreferenceKey
主要用于在视图层次结构中传递和读取自定义数据。- 需要定义自定义的
PreferenceKey
类型。
@AppStorage
作用和原理
@AppStorage
用于将值存储在用户默认数据库中,并在值改变时自动更新视图。
示例
import SwiftUI
struct AppStorageExample: View {
@AppStorage("username") var username: String = ""
var body: some View {
VStack {
TextField("Username", text: $username)
Text("Stored username: \(username)")
}
.padding()
}
}
注意事项
@AppStorage
适用于需要在应用重启后持久化存储数据的场景。- 使用时需要提供一个唯一的键来存储和检索数据。
@Environment(.openURL)
作用和原理
@Environment(\.openURL)
用于获取一个操作,用来打开指定的 URL。它通常用于在 SwiftUI 应用中处理 URL 打开操作。
示例
import SwiftUI
struct OpenURLExample: View {
@Environment(\.openURL) var openURL
var body: some View {
Button("Open Apple Website") {
openURL(URL(string: "https://www.apple.com")!)
}
.padding()
}
}
注意事项
@Environment(\.openURL)
只能用于打开 URL,不适用于其他用途。- 确保提供有效的 URL。
@FocusState
作用和原理
@FocusState
用于管理视图中的焦点状态,通常用于处理文本输入焦点。
示例
import SwiftUI
struct FocusStateExample: View {
@FocusState private var isFocused: Bool
var body: some View {
TextField("Enter text", text: .constant(""))
.focused($isFocused)
.padding()
Button("Toggle Focus") {
isFocused.toggle()
}
}
}
注意事项
@FocusState
用于管理输入焦点状态,需要与focused
修饰符一起使用。- 适用于表单输入和焦点管理。
属性包装器总结与对比
在 SwiftUI 中,属性包装器用于管理视图状态和数据绑定。以下是所有提到的属性包装器的简短总结和对比:
1. @State
- 作用:用于声明视图的本地状态。
- 特点:状态改变时会重新渲染视图。
- 示例:
@State private var isActive: Bool = false
2. @Binding
- 作用:在父子视图之间共享状态。
- 特点:父视图将状态传递给子视图进行双向绑定。
- 示例:
@Binding var isActive: Bool
3. @EnvironmentObject
- 作用:在视图层次结构中共享对象。
- 特点:视图可以从环境中读取共享的数据对象。
- 示例:
@EnvironmentObject var model: DataModel
4. @ObservedObject
- 作用:观察和响应对象的状态变化。
- 特点:用于在多个视图中观察同一个对象。
- 示例:
@ObservedObject var model: DataModel
5. @StateObject
- 作用:用于初始化和持有对象的状态。
- 特点:视图在对象改变时重新渲染。
- 示例:
@StateObject var model: DataModel
6. @AppStorage
- 作用:将值存储在用户默认数据库中。
- 特点:持久化存储数据,并在值改变时更新视图。
- 示例:
@AppStorage("username") var username: String = ""
7. @SceneStorage
- 作用:在场景中保存和恢复视图状态。
- 特点:在应用切换场景时保持状态。
- 示例:
@SceneStorage("text") var text: String = ""
8. @GestureState
- 作用:用于跟踪手势状态。
- 特点:适用于在手势识别过程中暂存状态。
- 示例:
@GestureState private var dragOffset = CGSize.zero
9. @Namespace
- 作用:创建动画的命名空间。
- 特点:用于定义视图动画的共享命名空间。
- 示例:
@Namespace var animation
10. @UIApplicationDelegateAdaptor
- 作用:将自定义的
UIApplicationDelegate
注入到 SwiftUI 应用中。 - 特点:适用于需要自定义应用代理行为的场景。
- 示例:
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
11. @Environment(.presentationMode)
- 作用:控制视图的显示和隐藏状态。
- 特点:用于模态视图的关闭操作。
- 示例:
@Environment(\.presentationMode) var presentationMode
12. @FocusState
- 作用:管理视图中的焦点状态。
- 特点:用于处理文本输入焦点。
- 示例:
@FocusState private var isFocused: Bool
13. @Environment(.locale)
- 作用:读取当前视图环境中的
Locale
对象。 - 特点:用于显示和处理区域设置相关的数据。
- 示例:
@Environment(\.locale) var locale
14. @Environment(.calendar)
- 作用:读取当前视图环境中的
Calendar
对象。 - 特点:用于显示和处理日期相关的数据。
- 示例:
@Environment(\.calendar) var calendar
15. @Environment(.timeZone)
- 作用:读取当前视图环境中的
TimeZone
对象。 - 特点:用于处理与时区相关的数据。
- 示例:
@Environment(\.timeZone) var timeZone
16. @Environment(.accessibilityEnabled)
- 作用:读取当前视图环境中的无障碍设置。
- 特点:用于调整视图以适应无障碍要求。
- 示例:
@Environment(\.accessibilityEnabled) var accessibilityEnabled
17. @Environment(.dismiss)
- 作用:获取一个操作,用来关闭当前视图。
- 特点:用于模态视图和导航视图的关闭操作。
- 示例:
@Environment(\.dismiss) var dismiss
18. @ObservedResults
- 作用:观察和管理来自 Realm 数据库的数据。
- 特点:在数据更改时自动更新视图。
- 示例:
@ObservedResults(Task.self) var tasks
19. @Query
- 作用:用于 Firestore 数据库的数据查询。
- 特点:自动查询数据,并在数据变化时更新视图。
- 示例:
@Query(collectionPath: "users") var users: [User]
20. @ObservedRealmObject
- 作用:观察和管理来自 Realm 数据库的对象。
- 特点:在数据更改时自动更新视图。
- 示例:
@ObservedRealmObject var task: Task
21. @PreferenceKey
- 作用:定义和读取视图层次结构中的自定义首选项值。
- 特点:在父视图和子视图之间传递数据。
- 示例:定义自定义
PreferenceKey
类型并使用。
22. @ScaledMetric
- 作用:根据用户的动态类型设置调整视图尺寸。
- 特点:确保视图在不同字体设置下具有良好的可读性和一致性。
- 示例:
@ScaledMetric var fontSize: CGFloat = 20
对比
- 状态管理:
@State
、@Binding
、@StateObject
、@ObservedObject
- 数据存储:
@AppStorage
、@SceneStorage
- 环境数据:
@Environment
、@EnvironmentObject
、@Environment(\.locale)
、@Environment(\.calendar)
、@Environment(\.timeZone)
、@Environment(\.accessibilityEnabled)
、@Environment(\.dismiss)
、@Environment(\.openURL)
- 手势状态:
@GestureState
- 动画:
@Namespace
- 应用代理:
@UIApplicationDelegateAdaptor
- 焦点管理:
@FocusState
- 数据查询:
@ObservedResults
、@Query
- 自定义首选项:
@PreferenceKey
- 动态尺寸:
@ScaledMetric
总结
SwiftUI 中的属性包装器提供了强大的工具集,使得开发者可以更方便地管理视图状态和数据绑定。每种属性包装器都有其特定的用途和使用场景,了解它们的作用、原理和用法,对于构建高效和健壮的 SwiftUI 应用至关重要。
通过本篇博客,我们详细介绍了 @AppStorage
、@Binding
、@EnvironmentObject
、@FocusedBinding
、@GestureState
、@Namespace
、@ObservedObject
、ObservableObject
、@SceneStorage
、@State
、@StateObject
和 @UIApplicationDelegateAdaptor
这些属性包装器。希望这些内容能帮助你在实际开发中更好地使用 SwiftUI 的强大功能。