从视图外部设置SwiftUI @EnvironmentObject [英] Setting a SwiftUI @EnvironmentObject from outside a view

查看:39
本文介绍了从视图外部设置SwiftUI @EnvironmentObject的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想让一个工作任务更新一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆