在将类信息从一个结构实例传递到另一个结构实例时,我遇到了麻烦,所以我一直在搞麻烦。
这行得通,因为我正在通过视图
// 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.
}
}
我收到一个运行时错误,该错误已在函数调用时添加了注释。
对于如何传递引用类型的实例,我感到很困惑,所以我确定我做错了很多事情,我们将不胜感激。
答案 0 :(得分:2)
这是行不通的,因为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)
}
}
答案 1 :(得分:0)
@ObservedObject var myObservedObject = MyObservedObject()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(myObservedObject)
}
}
这足以让您在ContentView的任何其他子视图中获得与myObservedObject
相同的environmentObject
实例。唯一的例外是.sheet
,您需要通过为.environmentObject(envObjInstance)
内部的视图使用相同的sheet
来为每个图纸手动将environemntObject传递给它们。
对于不符合该视图的结构,您可以只传递环境对象实例的包装值,并且对该传递实例的任何更改也将反映在您的视图中。
方法:
为您的结构声明一个变量:
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%有效,但是我不确定是否可以更简单。您甚至可能不需要将环境对象的包装值传递给该结构,就可以只传递简单值。