Home > Software engineering >  How to show an Alert dialog for push notifications when not using a ViewController
How to show an Alert dialog for push notifications when not using a ViewController

Time:07-21

I am building a SwiftUI app using Azure NotificationHubs and struggling with how to show an alert when a notification is received if I am not using a ViewController.

I am getting the notification, but don't know how to show a dialog from an event in AppDelegate since all the examples I have found are for ViewControllers.

func notificationHub(_ notificationHub: MSNotificationHub, didReceivePushNotification message: MSNotificationHubMessage) {

    print("notificationHub...")
    
    let title = message.title ?? ""
    let body = message.body ?? ""
    print("title: \(title)")
    print("body: \(body)")
    
    let userInfo = ["message": message]

    NotificationCenter.default.post(name: NSNotification.Name("MessageReceived"), object: nil, userInfo: userInfo)
    
    guard let aps = message.userInfo["aps"] as? [String: AnyObject] else {
        return
    }
    
    print("aps: \(aps)")

    if (UIApplication.shared.applicationState == .background) {
        print("Notification received in background")
    } else {
        print("Notification received in foreground")
    }

}

I don't get the message when in the background but when I click on the notification when the app is in the background I get the Notification received in foreground message.

I suppose the desired behavior is that if they click on message while the app is in the background it will go to the appropriate view. When it's in the foreground it will ask the user if they want to go to the view.

I have the navigation piece working, just need to know how to alert the user and respond to their choice.

In the Azure examples on GitHub they show:

class SetupViewController: MSNotificationHubDelegate // And other imports

// Set up the delegate
MSNotificationHub.setDelegate(self)

// Implement the method
func notificationHub(_ notificationHub: MSNotificationHub!, didReceivePushNotification notification: MSNotificationHubMessage!) {

    let title = notification.title ?? ""
    let body = notification.body ?? ""

    if (UIApplication.shared.applicationState == .background) {
        NSLog("Notification received in background: title:\"\(title)\" body:\"\(body)\"")
    } else {
        let alertController = UIAlertController(title: title, message: body, preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "OK", style: .cancel))

        self.present(alertController, animated: true)
    }
}

but I am not using a ViewController. This was a great resource as well but again they show a view controller (class ViewController: UIViewController).

I am new to iOS and Swift so I might be looking in the wrong area but I am essentially trying to show an alert dialog from an event triggered in the AppDelegate.

UPDATE

While working through the response below, I did come across this post recommending that I create a view with a @State private var showAlert = false; that could be bound to something I guess I change in the AppDelegate notificationHub method.

Is this the proper approach in SwiftUI vs UIWindowScene or UIApplication?

I did get this to work:

    if UIApplication.shared.windows.first != nil {
        UIApplication.shared.windows.first?.rootViewController!.present(alertController, animated: true)
    }

CodePudding user response:

You can get the rootViewController from UIApplication.shared.windows.first, then present an UIAlertController.

Usage:

//Force  
UIApplication.shared.windows.first?.rootViewController!.present(..)

//Safe
guard let viewController = UIApplication.shared.windows.first?.rootViewController else {return}
viewController.present(...)

Note:

UIApplication.shared.windows is deprecated in iOS 15, you can use UIWindowScene.windows.first in iOS 16.

  • Related