繁体   English   中英

@EnvironmentObject 可以与不是视图的普通结构一起使用吗?

[英]Can @EnvironmentObject be used with a plain struct that isn't a View?

我在将类信息从一个结构实例传递到另一个实例时遇到了麻烦,所以我一直在尝试解决问题。

这是有效的,因为我正在通过视图

// phone_testingApp.swift
import SwiftUI

@main
struct phone_testingApp: App {
    
    @ObservedObject var myObservedObject = MyObservedObject()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(myObservedObject)
        }
    }
}
// ContentView.swift

import SwiftUI
import Combine

struct ContentView: View {
    
    var subtract = MinusToObject()
    @EnvironmentObject var myNumber: MyObservedObject
    
    var body: some View {
        VStack{

            Text("The number is \(myNumber.theObservedObjectToPass)")
            
            MinusToObject()
                .environmentObject(myNumber)
        }
    }
}

class MyObservedObject: ObservableObject {
    @Published var theObservedObjectToPass = 5
}

struct MinusToObject: View {
    
    @EnvironmentObject var theObservedObject: MyObservedObject
    
    var body: some View {
        Text("Minus")
            .onTapGesture {
                theObservedObject.theObservedObjectToPass -= 1
            }
    }
}

但如果我尝试类似的东西,只是一个不符合 View 这样的普通结构

import SwiftUI
import Combine

struct ContentView: View {
    
    var subtract = MinusToObject()
    @EnvironmentObject var myNumber: MyObservedObject
    
    var body: some View {
        VStack{

            Text("The number is \(myNumber.theObservedObjectToPass)")
            
            Text("Minus")
                .onTapGesture {
                    subtract.subtractIt()
                }
        }
    }
}

class MyObservedObject: ObservableObject {
    @Published var theObservedObjectToPass = 5
}

struct MinusToObject {
    
    @EnvironmentObject var theObservedObject: MyObservedObject
    
        
            func subtractIt() {
                theObservedObject.theObservedObjectToPass -= 1 //Thread 1: Fatal error: No ObservableObject of type MyObservedObject found. A View.environmentObject(_:) for MyObservedObject may be missing as an ancestor of this view.
            }
}

我收到一个运行时错误,这是我在函数调用时注释的。

我对如何传递引用类型的实例感到非常困惑,所以我确定我做错了很多事情,任何帮助将不胜感激。

这是行不通的,因为EnvironmentObject注入仅在 SwiftUI View层次结构上执行到所有基于子视图的对象。

如果您希望任何旧对象访问共享实例,则必须手动创建一个单例并将其注入 SwiftUI 视图层次结构中。

class MyObservedObject: ObservableObject {
    static let shared = MyObservedObject()
    private init() { }

    @Published var theObservedObjectToPass = 5
}

/// you can use it in a plain object
struct MinusToObject {
    func subtractIt() {
        MyObservedObject.shared.theObservedObjectToPass -= 1 
    }
}

// you can use it in a view
struct ContentView: View {
    var body: some View {
        SomeOtherView()
            .environmentObject(MyObservedObject.shared)
    }
}
@ObservedObject var myObservedObject = MyObservedObject()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(myObservedObject)
        }
    }

这足以让您在 ContentView 的任何其他子视图中获得相同的myObservedObject实例作为environmentObject 唯一的例外是.sheet ,您需要通过使用相同的.environmentObject(envObjInstance)修饰符为sheet内的视图手动为每个 sheet .environmentObject(envObjInstance)修饰符。

对于不符合视图的结构,您可以将环境对象实例的包装值传递给它们,对此传递的实例的任何更改也将反映在您的视图中。

如何:

为您的结构声明一个变量:

struct AnyStruct {

var anEnvironmentObject: EnvironmentObject<TheEnvironmentObjectType>.Wrapper

.
.
.
}

然后在 SwiftUI 视图中,首先初始化您的结构:

struct someSwiftUIView: View {

@EnvironmentObject var myEnvObj: TheEnvironmentObjectType

var anyStruct: AnyStruct { AnyStruct.init(anEnvironmentObject: $myEnvObject) } 
// notice the dollar sign `$`

}

然后在您的AnyStruct ,您可以更改 environmentObject 中的值,并确保它们也将反映在您的视图中。 您只需要记住,您需要使用.wrappedValue为环境对象内的变量分配一个新值。 假设您的 environmentObject 中有一个名为observedInteger的变量:

extension AnyStruct {
func changeValueOfObservedIntegerToZero() {
self.anEnvironmentObject.observedInteger.wrappedValue = 0
// notice the `.wrappedValue`
}
}

请注意,这种方法 100% 对我有用,但我不确定是否可以更简单。 您甚至可能不需要将环境对象的包装值传递给结构体,您可以只传递简单值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM