[英]Can @EnvironmentObject be used with a plain struct that isn't a View?
I'm having troubles with passing class information from one struct instance to another, so I've been messing trying things out.我在将类信息从一个结构实例传递到另一个实例时遇到了麻烦,所以我一直在尝试解决问题。
This works because I'm passing through Views这是有效的,因为我正在通过视图
// 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
}
}
}
but if I try something similar with just a plain struct that doesn't conform to View like this但如果我尝试类似的东西,只是一个不符合 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.
}
}
I get a runtime error thats I've put commented in at the calling of the function.我收到一个运行时错误,这是我在函数调用时注释的。
I'm quite confused as to how to pass around an instance of a reference type, so I'm sure I'm doing many things wrong, and any help would be appreciated.我对如何传递引用类型的实例感到非常困惑,所以我确定我做错了很多事情,任何帮助将不胜感激。
That's not going to work because the EnvironmentObject
injection is performed on a SwiftUI View
hierarchy to all children view-based objects only.这是行不通的,因为EnvironmentObject
注入仅在 SwiftUI View
层次结构上执行到所有基于子视图的对象。
If you want any old object to access a shared instance, you'll have to create a singleton manually and inject that into the SwiftUI view hierarchy.如果您希望任何旧对象访问共享实例,则必须手动创建一个单例并将其注入 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)
}
}
this is enough for you to be able to get the same myObservedObject
instance in any other sub view of ContentView as an environmentObject
.这足以让您在 ContentView 的任何其他子视图中获得相同的myObservedObject
实例作为environmentObject
。 the only exceptions are .sheet
s which you'll need to pass the environemntObject to them manually for each sheet by using the same .environmentObject(envObjInstance)
modifier for views inside the sheet
.唯一的例外是.sheet
,您需要通过使用相同的.environmentObject(envObjInstance)
修饰符为sheet
内的视图手动为每个 sheet .environmentObject(envObjInstance)
修饰符。
for struct not conforming to the view, you can just pass the wrapped value of the instance of your environment object them and any changes to this passed instance will be reflected in your views too.对于不符合视图的结构,您可以将环境对象实例的包装值传递给它们,对此传递的实例的任何更改也将反映在您的视图中。
HOW:如何:
declare a variable for your struct :为您的结构声明一个变量:
struct AnyStruct {
var anEnvironmentObject: EnvironmentObject<TheEnvironmentObjectType>.Wrapper
.
.
.
}
then in a SwiftUI view, first initialize your struct:然后在 SwiftUI 视图中,首先初始化您的结构:
struct someSwiftUIView: View {
@EnvironmentObject var myEnvObj: TheEnvironmentObjectType
var anyStruct: AnyStruct { AnyStruct.init(anEnvironmentObject: $myEnvObject) }
// notice the dollar sign `$`
}
then in your AnyStruct
, you can change the values in the environmentObject and be sure that they will be reflected in your views too.然后在您的AnyStruct
,您可以更改 environmentObject 中的值,并确保它们也将反映在您的视图中。 you just need to remember that you need to use .wrappedValue
to assign a new value to a variable that is inside your environment object.您只需要记住,您需要使用.wrappedValue
为环境对象内的变量分配一个新值。 assuming your environmentObject has a variable in it named observedInteger
:假设您的 environmentObject 中有一个名为observedInteger
的变量:
extension AnyStruct {
func changeValueOfObservedIntegerToZero() {
self.anEnvironmentObject.observedInteger.wrappedValue = 0
// notice the `.wrappedValue`
}
}
note this approach has 100% worked for me, but i'm not sure if can be simpler or not.请注意,这种方法 100% 对我有用,但我不确定是否可以更简单。 you might even not need to pass the wrapped value of your environment object to the struct, you might be able to just passed the simple value.您甚至可能不需要将环境对象的包装值传递给结构体,您可以只传递简单值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.