繁体   English   中英

从视图外部设置 SwiftUI @EnvironmentObject

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

我想让一个工作任务更新 SwiftUI 视图。

worker 任务正忙于执行应用程序的程序性工作——播放声音和触发基于计时器的事件。 我想在这些计时器事件期间 SwiftUI 视图中的几个图标 flash。 所以我想在这些图标视图中触发视图刷新。

因此,我创建了一个名为 Settings 的 environmentObject。 它在 App Delegate 中实例化,并附加到 SceneDelegate 中的根视图。

设置 object 在 SwiftUI 视图层次结构中工作得很好。

问题是可怕的:

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

我认为问题在于工人 class 是在 AppDelegate 中实例化的,而 Settings 在实例化时还不是 ObservableObject。 但我很困惑。

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

它与工作程序 class 一起在 AppDelegate 中实例化:

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

它被传递给 SceneDelegate:

            window.rootViewController = UIHostingController(rootView: contentView
                .environmentObject(settings)

使用设置的子视图查看环境 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
            }
        }
    }
}

工作人员 class 在 SwiftUI 视图层次结构中被称为按钮操作。

在工作人员 class 内部,我尝试附加到设置环境 object:

import Combine

public class WorkerClass : NSObject, ObservableObject {

    @EnvironmentObject var settings: Settings

在通过计时器调用的方法中,我尝试更新环境 object 中的变量:

       settings.arrowsOn = !settings.arrowsOn
        print("Arrows are \(settings.arrowsOn)")

...当我发现我实际上未能正确连接到环境 object 时。

我错过了什么?

在此先感谢您的任何见解...

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

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

以及创建时

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

暂无
暂无

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

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