SwiftUI 中的状态管理

408 阅读3分钟

在Flutter中,有多种状态管理方案可供选择:

  1. setState 最简单和直接的状态管理方式,用于在单个Widget内部管理局部状态。
  2. InheritedWidget 用于在Widget树中向下传递数据和状态,非常适合构建一个全局的、可以共享的状态。
  3. Provider 基于InheritedWidget,提供了更加简洁和灵活的API
  4. Bloc (Business Logic Component) 将业务逻辑和UI分离的状态管理方案,适合大型应用。
  5. Riverpod 一种更现代化和灵活的Provider替代方案,支持更好的测试和组合。
  6. GetX 一种轻量级且高性能的状态管理、依赖注入和路由管理方案。

那在SwiftUI 当中是如何处理状态管理的呢? 在SwiftUI中,状态管理是一个重要的概念,它帮助我们保持UI和数据的一致性。以下是关于@State, @Binding, @ObservedObject, @EnvironmentObject, 和 @StateObject 的示例和注释。

@State

@State 用于在视图内部声明一个状态变量。SwiftUI 会观察这个状态,一旦状态发生变化,视图会自动重新渲染。

import SwiftUI

struct CounterView: View {
    @State private var count: Int = 0  // 声明一个状态变量
    var body: some View {
        VStack {
            Text("Count: \(count)")
            Button(action: {
                count += 1  // 点击按钮时状态变化
            }) {
                Text("Increment")
            }
        }
    }
}

@Binding

@Binding 用于在不同视图之间共享状态。它通常在子视图中声明,以便父视图将状态传递给子视图。

import SwiftUI

struct ParentView: View {
    @State private var count: Int = 0  // 父视图中的状态变量
    
    var body: some View {
        VStack {
            Text("Parent Count: \(count)")
            ChildView(count: $count)  // 通过绑定将状态传递给子视图
        }
    }
}

struct ChildView: View {
    @Binding var count: Int  // 子视图中的绑定变量
    
    var body: some View {
        Button(action: {
            count += 1  // 修改绑定的状态
        }) {
            Text("Increment in Child")
        }
    }
}

@ObservedObject

@ObservedObject 用于观察一个遵循 ObservableObject 协议的对象。对象内部有变化时,视图会自动重新渲染。

import SwiftUI
import Combine

class CountModel: ObservableObject {
    @Published var count: Int = 0  // 通过 @Published 标记的变量会触发视图更新
}

struct ContentView: View {
    @ObservedObject var model = CountModel()  // 观察一个可观察对象
    
    var body: some View {
        VStack {
            Text("Count: \(model.count)")
            Button(action: {
                model.count += 1  // 修改可观察对象中的变量
            }) {
                Text("Increment")
            }
        }
    }
}

@StateObject

@StateObject 类似于 @ObservedObject,但它用于在视图内声明和管理一个可观察对象的生命周期,通常用于视图首次创建时初始化对象。

import SwiftUI

class CountModel: ObservableObject {
    @Published var count: Int = 0
}

struct ContentView: View {
    @StateObject private var model = CountModel()  // StateObject 管理对象的生命周期
    
    var body: some View {
        VStack {
            Text("Count: \(model.count)")
            Button(action: {
                model.count += 1
            }) {
                Text("Increment")
            }
        }
    }
}

@EnvironmentObject

@EnvironmentObject 用于在视图层级之间共享状态,通常用于全局状态管理。

import SwiftUI

class GlobalCountModel: ObservableObject {
    @Published var count: Int = 0
}

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ParentView().environmentObject(GlobalCountModel())  // 将环境对象注入视图层级
        }
    }
}

struct ParentView: View {
    @EnvironmentObject var model: GlobalCountModel  // 从环境中获取对象
    
    var body: some View {
        VStack {
            Text("Parent Count: \(model.count)")
            ChildView()
        }
    }
}

struct ChildView: View {
    @EnvironmentObject var model: GlobalCountModel  // 从环境中获取对象
    
    var body: some View {
        Button(action: {
            model.count += 1
        }) {
            Text("Increment in Child")
        }
    }
}

这些示例展示了SwiftUI中不同的状态管理属性和它们的使用场景。选择合适的属性能够帮助你更好地管理状态,使你的应用更加健壮和可维护。