简体   繁体   中英

SwiftUI - How to trigger an Alert from a seperate class

I have a class called Startup. In this class, I have a bunch of functions that I call from SceneDelegate when the app starts.

for example:

class Startup {

   func doThis() {

     print("I'm doing this")

   }
}

At one point, it may download data, if its necessary. When this happens, I'd like to trigger an Alert w/ Activity Indicator to block the UI from user input until things are completed.

I have the Activity Indicator Alert all set up in ContentView, which triggers on an EnvironmentObject var Bool. So all I need to do to activate this UI blocking alert is to toggle() my env var.

The problem I am having is that I can not trigger this env var from within my class. I have tried the following:

When I put the @EnvironmentObject var dataBusy: DataBusy and call it from within a function: dataBusy.isBusy = true , I get the error message:

Fatal error: No ObservableObject of type DataBusy found.

Which indicates that I need to shove the env object into the environment of the class when it is instantiated, however, when I try to do that, I get:

Value of tuple type '()' has no member 'environmentObject'

So, I can not add this env var into this class object.

Trying to use:

@ObservedObject var dataBusy = DataBusy()

In my class seems to not error out, but toggling this does not do anything to trigger my event.

I can't think of any other way to communicate with my View from this startup class.

Any ideas?

The following code works, you many find what you miss or misunderstanding.

        class Env:  NSObject,  ObservableObject{
            @Published var isEnabled = false
        }

        struct AlertTest: View {

            @EnvironmentObject var envObject: Env

            var body: some View {
                Text("board").alert(isPresented: $envObject.isEnabled) { () -> Alert in
                    return Alert(title: Text("hello"))
                }
        }
        }


        //Scene Delegate
        func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

            let m = Env()
            let contentView =  AlertTest().environmentObject(m)

            if let windowScene = scene as? UIWindowScene {
                let window = UIWindow(windowScene: windowScene)
                window.rootViewController = UIHostingController(rootView: contentView)
                self.window = window
                window.makeKeyAndVisible()
            }

            Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { (Timer) in
                DispatchQueue.main.async {
                    m.isEnabled = true
                }
            }

        }

Got it..

E.Coms answer is very good, however, I was calling the func which would be responsible for this action from within another function, within another function from this other class, not directly from the scene delegate.

To get it, I had to pass the DataBusy object dataBusy from my scene delegate to my class func as a parameter:

//Scene Delegate:

let dataBusy = DataBusy() //my Observed Object Class
let myClass = MyClass();  //instantiate my class 

myClass.myFunc(data: dataBusy) //pass the object through to the class function

This way, when the time arises within my class function, I can toggle the variable and it all works perfectly.

Thank you for your input.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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