SwiftUI中的ViewModel注入方式

@StateObject

@StateObject用于创建和持有ViewModel实例。

  • Name
    特点
    Type
    features
    Description
    • 由视图持有和管理生命周期
    • 视图重建时保持状态
    • 适用于视图创建的VM
    • 通常在父视图中声明
  • Name
    使用场景
    Type
    usage
    Description
    • 视图自己创建VM
    • VM需要在视图生命周期内保持
    • 不需要共享VM实例

@StateObject示例

class UserViewModel: ObservableObject {
    @Published var name: String = ""
    
    func updateName(_ newName: String) {
        name = newName
    }
}

struct UserView: View {
    @StateObject private var viewModel = UserViewModel()
    
    var body: some View {
        TextField("Name", text: $viewModel.name)
    }
}

@ObservedObject

@ObservedObject用于接收外部传入的ViewModel实例。

  • Name
    特点
    Type
    features
    Description
    • 不创建VM实例
    • 依赖外部传入
    • 视图重建可能重置
    • 适用于子视图
  • Name
    使用场景
    Type
    usage
    Description
    • 从父视图传递VM
    • VM需要在多个视图共享
    • 子视图观察父视图的VM

@ObservedObject示例

struct ProfileView: View {
    @ObservedObject var viewModel: UserViewModel
    
    var body: some View {
        VStack {
            Text("Name: \(viewModel.name)")
            Button("Reset") {
                viewModel.updateName("")
            }
        }
    }
}

struct ParentView: View {
    @StateObject private var userVM = UserViewModel()
    
    var body: some View {
        ProfileView(viewModel: userVM)
    }
}

@EnvironmentObject

@EnvironmentObject用于全局共享ViewModel实例。

  • Name
    特点
    Type
    features
    Description
    • 全局依赖注入
    • 无需显式传递
    • 适用于深层视图
    • 必须由祖先视图提供
  • Name
    使用场景
    Type
    usage
    Description
    • 全局状态管理
    • 深层视图需要访问VM
    • 避免多层传递

@EnvironmentObject示例

class AppViewModel: ObservableObject {
    @Published var isLoggedIn = false
}

struct RootView: View {
    @StateObject private var appVM = AppViewModel()
    
    var body: some View {
        ContentView()
            .environmentObject(appVM)
    }
}

struct ContentView: View {
    @EnvironmentObject var appVM: AppViewModel
    
    var body: some View {
        if appVM.isLoggedIn {
            HomeView()
        } else {
            LoginView()
        }
    }
}

这篇文章对你有用吗?