简体   繁体   English

从视图外部设置 SwiftUI @EnvironmentObject

[英]Setting a SwiftUI @EnvironmentObject from outside a view

I'd like to have a worker task update a SwiftUI view.我想让一个工作任务更新 SwiftUI 视图。

The worker task is busy doing the procedural work of the application - playing sounds, and firing timer-based events. worker 任务正忙于执行应用程序的程序性工作——播放声音和触发基于计时器的事件。 I'd like to to flash several icons in a SwiftUI view during those timer events.我想在这些计时器事件期间 SwiftUI 视图中的几个图标 flash。 So I want to trigger a view refresh in those icon views.所以我想在这些图标视图中触发视图刷新。

So, I created an environmentObject called Settings.因此,我创建了一个名为 Settings 的 environmentObject。 It's instantiated in the App Delegate, and attached to the root view in the SceneDelegate.它在 App Delegate 中实例化,并附加到 SceneDelegate 中的根视图。

The Settings object works just fine inside the SwiftUI View hierarchy.设置 object 在 SwiftUI 视图层次结构中工作得很好。

The problem is the dreaded:问题是可怕的:

Fatal error: No ObservableObject of type Settings found. A View.environmentObject(_:) for Settings may be missing as an ancestor of this view.

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.我认为问题在于工人 class 是在 AppDelegate 中实例化的,而 Settings 在实例化时还不是 ObservableObject。 But I'm confused.但我很困惑。

The environment object is straightforward:环境 object 很简单:

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>()

It's instantiated, along with the worker class, in the AppDelegate:它与工作程序 class 一起在 AppDelegate 中实例化:

let settings = Settings()
...
var workerClass  = WorkerClass()
var leftArrow = LeftArrowView()

And it's passed to the SceneDelegate:它被传递给 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:使用设置的子视图查看环境 object 以在打开或关闭 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
            }
        }
    }
}

The worker class is called as a Button action from higher up in the SwiftUI view hierarchy.工作人员 class 在 SwiftUI 视图层次结构中被称为按钮操作。

Inside the worker class I attempt to attach to the settings environment object:在工作人员 class 内部,我尝试附加到设置环境 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:在通过计时器调用的方法中,我尝试更新环境 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. ...当我发现我实际上未能正确连接到环境 object 时。

What did I miss?我错过了什么?

Thanks in advance for any insights...在此先感谢您的任何见解...

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 @EnvironmentObject包装器只能在 SwiftUI 视图中使用,在其他地方您可以以常规方式使用引用类型,所以这里是可能的解决方案

public class WorkerClass : NSObject, ObservableObject {
    var settings: Settings    // reference property

and when create以及创建时

let settings = Settings()
...
var workerClass  = WorkerClass(settings: settings) // << same settings as in view

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

相关问题 在 SwiftUI 中通过摇动手势(使用 UIKit)设置 EnvironmentObject 不会更新视图 - Setting EnvironmentObject from a Shake Gesture (using UIKit) in SwiftUI doesn't update View SwiftUI 视图未更新为 EnvironmentObject 更改 - SwiftUI view is not updating to EnvironmentObject change SwiftUI EnvironmentObject 与 View 不同步 - SwiftUI EnvironmentObject out of sync with View 从 SwiftUI 中的 ViewModel 访问 EnvironmentObject - Access EnvironmentObject from ViewModel in SwiftUI 如何在 Swiftui View 函数中使用 EnvironmentObject? - how to use EnvironmentObject in a Swiftui View function? SwiftUI - 如何将 EnvironmentObject 传递到视图模型中? - SwiftUI - How to pass EnvironmentObject into View Model? SwiftUI A View.environmentObject(_:) for 可能作为此视图的祖先丢失。:文件 - SwiftUI A View.environmentObject(_:) for may be missing as an ancestor of this view.: file SwiftUI EnvironmentObject 不会重绘当前视图,而是重绘其父视图 - SwiftUI EnvironmentObject does not redraw the current view but its parent view SwiftUI iOS 14 视图不会使用 @EnvironmentObject 更新 @Published 数组 - SwiftUI iOS 14 View does not Update @Published Array with @EnvironmentObject 无法使用 @EnvironmentObject SwiftUI 更新先前视图上的文本 - Can't Update Text on Previous View using @EnvironmentObject SwiftUI
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM