如何实现三个同类型EnvironmentObject实例?SwiftUI设计方案咨询
SwiftUI中同类型的EnvironmentObject确实只能在环境中存在一个,直接添加多个同类型实例会导致后续实例覆盖前面的,以下是几种可行的解决方案:
方案一:用容器类统一管理多个实例
创建一个容器类封装所有PredictService实例,将容器作为单个EnvironmentObject注入环境,子视图通过容器访问各个独立服务。
示例代码:
// 定义容器类 class PredictServicesContainer: ObservableObject { let service1 = PredictService() let service2 = PredictService() let service3 = PredictService() } // 在App中注入容器 struct MyAPP: App { @StateObject private var servicesContainer = PredictServicesContainer() var body: some Scene { WindowGroup { ContentView() .environmentObject(servicesContainer) } } } // 在视图中使用 struct ContentView: View { @EnvironmentObject private var servicesContainer: PredictServicesContainer var body: some View { VStack { RepeatView(predictService: servicesContainer.service1) RepeatView(predictService: servicesContainer.service2) RepeatView(predictService: servicesContainer.service3) } } } // 重复子视图 struct RepeatView: View { let predictService: PredictService var body: some View { // 视图内容 } }
方案二:自定义EnvironmentKey分别注入
通过自定义环境键,为每个PredictService实例分配唯一标识,实现单独注入和获取,不依赖类型区分。
示例代码:
// 自定义三个环境键 private struct PredictService1Key: EnvironmentKey { static let defaultValue: PredictService = PredictService() } private struct PredictService2Key: EnvironmentKey { static let defaultValue: PredictService = PredictService() } private struct PredictService3Key: EnvironmentKey { static let defaultValue: PredictService = PredictService() } // 扩展EnvironmentValues添加访问器 extension EnvironmentValues { var predictService1: PredictService { get { self[PredictService1Key.self] } set { self[PredictService1Key.self] = newValue } } var predictService2: PredictService { get { self[PredictService2Key.self] } set { self[PredictService2Key.self] = newValue } } var predictService3: PredictService { get { self[PredictService3Key.self] } set { self[PredictService3Key.self] = newValue } } } // 在App中注入 struct MyAPP: App { @StateObject private var service1 = PredictService() @StateObject private var service2 = PredictService() @StateObject private var service3 = PredictService() var body: some Scene { WindowGroup { ContentView() .environment(\.predictService1, service1) .environment(\.predictService2, service2) .environment(\.predictService3, service3) } } } // 在视图中使用 struct ContentView: View { @Environment(\.predictService1) private var service1 @Environment(\.predictService2) private var service2 @Environment(\.predictService3) private var service3 var body: some View { VStack { RepeatView(predictService: service1) RepeatView(predictService: service2) RepeatView(predictService: service3) } } }
方案三:直接给子视图传递实例
如果三个重复视图直接在ContentView中声明,可直接将服务实例传递给子视图,无需依赖环境,实现简单直观:
struct MyAPP: App { @StateObject private var service1 = PredictService() @StateObject private var service2 = PredictService() @StateObject private var service3 = PredictService() var body: some Scene { WindowGroup { ContentView( service1: service1, service2: service2, service3: service3 ) } } } struct ContentView: View { let service1: PredictService let service2: PredictService let service3: PredictService var body: some View { VStack { RepeatView(predictService: service1) RepeatView(predictService: service2) RepeatView(predictService: service3) } } }
内容的提问来源于stack exchange,提问作者erotsppa
相关产品推荐
相关产品推荐

