@State @ObservedObject @StateObject 的使用
swift
import SwiftUI
class CountModel: ObservableObject {
@Published var count: Int = 0 // 通过 @Published 标记的变量会触发视图更新
init() {
print("TimerModel initialized at \(count)")
}
}
struct ContentView: View {
@State private var count: Int = 0 // 声明一个状态变量
@ObservedObject private var model = CountModel() // 观察一个可观察对象
@StateObject private var model2 = CountModel()
var body: some View {
VStack {
Text("Parent Count: \(count)")
Button {
count += 1 // 修改可观察对象中的变量
} label: {
Text("parent count")
}
Text("parent model Count \(model.count)")
Button {
model.count += 1 // 修改可观察对象中的变量
model2.count += 1 // 修改可观察对象中的变量
} label: {
Text("model count")
}
ChildView(count: $count, model: model, model2: model2) // 通过绑定将状态传递给子视图
}
}
}
struct ChildView: View {
@Binding var count: Int // 子视图中的绑定变量
@ObservedObject var model: CountModel
@ObservedObject var model2: CountModel
var body: some View {
Button(action: {
count += 1 // 修改绑定的状态
}) {
Text("Child \(count) modelcount: \(model.count) model2 count \(model2.count)")
}
}
}
#Preview {
ContentView()
}

使用@ObservedObject的对象直接传递给子类的效果和@StateObject虽然可以达到同样的效果,但是不安全。
@EnvironmentObject @Environment @AppStorage
@EnvironmentObject 需要将数据从父类传递给子类;
@AppStorage 全局可用,使用UserDefaults也可以修改数据;
// 可观察对象,用来存储应用的状态
class UserSettings: ObservableObject {
@Published var username: String = "Guest"
}
struct ContentView2: View {
@EnvironmentObject var userSettings: UserSettings // 从环境中获取共享的数据
@Environment(\.appTheme) var appTheme
@AppStorage("isDarkMode") var isDarkMode: Bool = false
var body: some View {
VStack {
Text("Hello, \(userSettings.username) isDarkMode: \(isDarkMode)")
.background(appTheme.backgroundColor) // 使用环境中传递的主题背景色
.foregroundColor(appTheme.textColor) // 使用环境中传递的主题文字色
Button("Change Username in Content") {
userSettings.username = "Content" // 修改用户名,视图会自动更新
isDarkMode.toggle()
}
}
.padding()
}
}
struct AnotherView: View {
@EnvironmentObject var userSettings: UserSettings
// @AppStorage
// @AppStorage 是一种属性包装器,用于将数据存储到应用的 UserDefaults 中,并且能够使得数据在视图间保持同步。
// 它允许你轻松地从 UserDefaults 获取和存储数据,同时自动处理视图的更新。。
// 它非常适合在应用程序中持久化小型设置或状态,如主题、语言选择等。当 UserDefaults 中的数据发生变化时,视图会自动重新渲染。
@AppStorage("isDarkMode") var isDarkMode: Bool = false
var body: some View {
VStack {
Text("AnotherView Hello: \(userSettings.username) isDarkMode: \(isDarkMode)")
Button("Change Username in Another View") {
userSettings.username = "Another"
UserDefaults().set(true, forKey: "isDarkMode")
}
ThreeLevelView()
}
}
}
struct ThreeLevelView: View {
@EnvironmentObject var userSettings: UserSettings
var body: some View {
VStack {
Text("ThreeLevelView Hello: \(userSettings.username)")
Button("Change Username in ThreeLevelView") {
userSettings.username = "Three Level"
}
}
}
}
struct ParentView: View {
@EnvironmentObject var userSettings: UserSettings
var body: some View {
VStack {
ContentView2()
AnotherView()
}
}
}
struct HomePageView: View {
@StateObject private var userSettings = UserSettings()
let lightTheme = AppTheme(backgroundColor: .white, textColor: .black)
let darkTheme = AppTheme(backgroundColor: .red, textColor: .white)
@Environment(\.colorScheme) var colorScheme1 // 获取当前的颜色模式
@Environment(\.horizontalSizeClass) var sizeClass // 获取当前设备的横向布局类
var body: some View {
VStack {
Text("HomePage Hello: \(userSettings.username)")
Button("Change Username in HomePage") {
userSettings.username = "HomePage"
}
}
// @Environment
// @Environment属性包装器用于从视图的环境中获取系统提供的或由父视图注入的共享数据,而不需要显示地通过属性传递数据。
// 它能让你访问与当前环境相关的信息,并在视图中进行响应式更新。
// 基本语法: @Environment(\.key) var value@Environment(\.key) var value
// key:系统环境值的键或自定义的环境键,用来标识要获取的环境数据.
// value:存储在环境中的实际值,可以是任何类型.
// SwiftUI 提供了一些常用的系统级别的环境数据,比如: 当前的颜色模式,设备的横向布局类
ParentView().environmentObject(userSettings).environment(\.appTheme, darkTheme)
}
}
struct AppTheme {
var backgroundColor: Color
var textColor: Color
}
struct AppThemeKey: EnvironmentKey {
// 为这个环境键提供默认值
static let defaultValue: AppTheme = .init(backgroundColor: .red, textColor: .yellow)
}
extension EnvironmentValues {
var appTheme: AppTheme {
get { self[AppThemeKey.self] }
set { self[AppThemeKey.self] = newValue }
}
}
#Preview {
HomePageView()
}
其它链接:
SwiftUI 中的状态管理