Confusing About @Environmentobject in Swiftui

Setting a SwiftUI @EnvironmentObject from outside a view

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

and when create

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

Having an @EnvironmentObject in the view causes Tasks to be executed on the main thread

As far as I can tell, your code, with or without the @EnvrionmentObject, should always block the main thread. The fact that it doesn't without @EnvironmentObject may be a bug, but not the other way around.

In your example, you block the main thread -- you call out to an async function that runs on the context inherited from its parent. Its parent is a View, and runs on the main actor.

Usually in this situation, there's confusion about what actually runs something outside of the inherited context. You mentioned using Task.detached, but as long as your function was still marked async on the parent, with no other modifications, in would still end up running on the main actor.

To avoid inheriting the context of the parent, you could, for example, mark it as nonisolated:

nonisolated func asyncWait() async {
let continueTime: Date = .second, value: 2, to: Date())!
while (Date() < continueTime) {}

Or, you could move the function somewhere (like to an ObservableObject outside of the View) that does not explicitly run on the main actor like the View does.

Note that there's also a little bit of deception here because you've marked the function as async, but it doesn't actually do any async work -- it just blocks the context that it's running on.

Related Topics

Leave a reply