从视图外部设置SwiftUI @EnvironmentObject [英] Setting a SwiftUI @EnvironmentObject from outside a view
问题描述
我想让一个工作任务更新一个SwiftUI视图.
I'd like to have a worker task update a SwiftUI view.
worker任务正在忙于执行应用程序的程序性工作-播放声音和触发基于计时器的事件.我想在这些计时器事件期间在SwiftUI视图中闪烁几个图标.因此,我想在这些图标视图中触发视图刷新.
The worker task is busy doing the procedural work of the application - playing sounds, and firing timer-based events. I'd like to to flash several icons in a SwiftUI view during those timer events. So I want to trigger a view refresh in those icon views.
因此,我创建了一个名为Settings的环境对象.它在App Delegate中实例化,并附加到SceneDelegate的根视图.
So, I created an environmentObject called Settings. It's instantiated in the App Delegate, and attached to the root view in the SceneDelegate.
Settings对象在SwiftUI View层次结构内正常工作.
The Settings object works just fine inside the SwiftUI View hierarchy.
问题是可怕的:
Fatal error: No ObservableObject of type Settings found. A View.environmentObject(_:) for Settings may be missing as an ancestor of this view.
我认为问题在于工作类在AppDelegate中实例化,并且设置在实例化时还不是ObservableObject.但是我很困惑.
I think that the problem is that the worker class is instantiated in the AppDelegate, and Settings is not yet an ObservableObject yet when it's instantiated. But I'm confused.
环境对象很简单:
import SwiftUI
import Combine
final class Settings: ObservableObject {
@Published var showMenu: Bool = true
@Published var lessonNum: Int = 0
@Published var arrowsOn: Bool = false {
willSet {
willChange.send(self)
}
}
}
let willChange = PassthroughSubject<Settings, Never>()
它与worker类一起在AppDelegate中实例化:
It's instantiated, along with the worker class, in the AppDelegate:
let settings = Settings()
...
var workerClass = WorkerClass()
var leftArrow = LeftArrowView()
它已传递给SceneDelegate:
And it's passed to the SceneDelegate:
window.rootViewController = UIHostingController(rootView: contentView
.environmentObject(settings)
使用设置的子视图查看环境对象以在打开或关闭状态下绘制图标:
The sub view that uses settings looks at the environment object to draw the icon in either the on or off state:
import SwiftUI
struct LeftArrowView: View {
@EnvironmentObject var settings: Settings
let leftArrowOnImage = Image("Arrow Left On").renderingMode(.original)
let leftArrowOffImage = Image("Arrow Left Off").renderingMode(.original)
var body: some View {
ZStack {
if settings.arrowsOn {
leftArrowOnImage
} else {
leftArrowOffImage
}
}
}
}
在SwiftUI视图层次结构中,从上层将worker类称为Button操作.
The worker class is called as a Button action from higher up in the SwiftUI view hierarchy.
我尝试在worker类中附加到设置环境对象:
Inside the worker class I attempt to attach to the settings environment object:
import Combine
public class WorkerClass : NSObject, ObservableObject {
@EnvironmentObject var settings: Settings
在通过计时器调用的方法中,我尝试更新环境对象中的变量:
and inside a method that's invoked via a timer, I attempt to update a variable in the environment object:
settings.arrowsOn = !settings.arrowsOn
print("Arrows are \(settings.arrowsOn)")
...这是当我发现实际上无法正确附加到环境对象时.
... which is when I discover that I failed to actually attach properly to the environment object.
我想念什么?
在此先感谢您的见解...
Thanks in advance for any insights...
推荐答案
@EnvironmentObject
包装器仅在SwiftUI视图中使用,在其他地方,您可以常规方式使用引用类型,因此这是可能的解决方案
The @EnvironmentObject
wrapper is only to be used inside SwiftUI view, in other places you can use reference types in regular way, so here is possible solution
public class WorkerClass : NSObject, ObservableObject {
var settings: Settings // reference property
以及创建时
let settings = Settings()
...
var workerClass = WorkerClass(settings: settings) // << same settings as in view
这篇关于从视图外部设置SwiftUI @EnvironmentObject的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!