跳转到主要内容

SwiftUI 数据绑定与状态管理核心概念

1. @State

  • 用于管理单个视图内的局部状态。
  • 数据变化时,视图会自动重新渲染。

2. @Binding

  • 用于在父视图和子视图之间共享数据。使用 @Binding 将数据传递给子视图,实现双向绑定。
  • 子视图通过 @Binding 修改父视图的状态。

3. @EnvironmentObject

  • 用于在多个视图中共享数据。
  • 适合全局状态管理。

4. @Published

  • 用来标记 可被观察的属性 的,它通常用于 ObservableObject 类中。
  • 当 @Published 标记的属性发生变化时,任何监听该对象的视图都会自动刷新。

5. @ObservedObject

  • 通常结合 ObservableObject 协议使用。
  • 用来在视图中监听 ObservableObject 的。当 @ObservedObject 监听的对象中任何 @Published 的属性发生变化时,绑定的视图会自动刷新。
  • 一般用在子视图中接受父视图的ObservableObject。

6. @StateObject

  • 用来 创建并管理 ObservableObject 的实例。
  • 它负责绑定该对象的生命周期,确保对象在视图多次重建时不会被重复初始化。
  • 一般用在父视图中创建ObservableObject。
import SwiftUI
import Combine

class UserSettings: ObservableObject {
    @Published var username: String = "初始用户名"
    @Published var isDarkMode: Bool = false
}

struct ParentView: View {
    @StateObject var settings = UserSettings() // 创建数据对象并绑定生命周期

    var body: some View {
        ChildView(settings: settings)
    }
}

struct ChildView: View {
    @ObservedObject var settings: UserSettings // 子视图监听传入的对象

    var body: some View {
        VStack {
            Text("用户名: \(settings.username)")
            Button("修改用户名") {
                settings.username = "新用户名" // 修改会自动更新视图
            }
        }
    }
}

.environmentObject 的作用

  1. 全局状态共享:提供了一种方便的方式来共享数据模型,适合用于多个视图间共享全局性或跨层级的数据,比如用户设置、登录状态、应用配置等。
  2. 简化数据传递:避免通过 init 方法显式地将状态数据逐层从父视图传递到子视图,简化代码结构。
  3. 自动 UI 刷新:当数据模型中的属性发生变化时,任何依赖该数据的视图都会自动更新 UI。 使用注意:
  • 被共享的数据模型需要遵循 ObservableObject 协议,并使用 @Published 修饰需要被观察的属性。
  • 在视图层级的顶层,通过 .environmentObject(_:) 方法将数据模型注入到环境中。
  • 在需要访问数据的子视图中,声明一个 @EnvironmentObject 属性以使用共享数据模型。
class appState: ObservableObject{
    @Published var isLogin = false;
}
struct LoginView:View {
    @EnvironmentObject var appstate: appState
    var body: some View {
        Button(appstate.isLogin ? "登出":"登录"){
            appstate.isLogin.toggle()
        }
    }
}

struct ContentView3: View {
    @StateObject var myapp = appState()
    var body: some View {
        LoginView()
            .environmentObject(myapp)
            .padding()
    }
}