简体   繁体   中英

How do I present a UIAlertController in SwiftUI?

In UIKit, it is common to present UIAlertController for modal pop up alert messages in response to some action.

Is there a modal alert controller type in SwiftUI?

Is there a way to present a UIAlertController from SwiftUI classes? It seems like this may be possible using UIViewControllerRepresentable but not sure if that is required?

Use Alert instead.

import SwiftUI

struct SwiftUIView: View {
    @State private var showAlert = false;

    var body: some View {
        Button(action: { self.showAlert = true }) {
            Text("Show alert")
        }.alert(
            isPresented: $showAlert,
            content: { Alert(title: Text("Hello world")) }
        )
    }
}

Bind to isPresented in order to control the presentation.

This just works:

class func alertMessage(title: String, message: String) {
    let alertVC = UIAlertController(title: title, message: message, preferredStyle: .alert)
    let okAction = UIAlertAction(title: "OK", style: .default) { (action: UIAlertAction) in
    }
    alertVC.addAction(okAction)
    
    let viewController = UIApplication.shared.windows.first!.rootViewController!
    viewController.present(alertVC, animated: true, completion: nil)
}

Put it in a Helper-Class.

Usage:

Helper.alertMessage(title: "Test-Title", message: "It works - even in SwiftUI")

You can present UIKit Alert in SwiftUI using notificationCenter

At SceneDelegate.swift on "func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)" insert this code {

   NotificationCenter.default.addObserver(self, selector: #selector(self.showAlert), name: Notification.Name("showAlert"), object: nil)

and add this function

  @objc private func showAlert(notification: NSNotification){
        let msg: String = notification.object as! String
        let alert =  UIAlertController(title: "Title", message: msg, preferredStyle: .alert)
        let cancelAction = UIAlertAction(title: "οκ", style: .cancel) { (action) in
        }
        alert.addAction(cancelAction)
        DispatchQueue.main.async {
            self.window?.rootViewController?.present(alert, animated: true, completion: nil)
        }
    }

Now you can make the app to appear a message with UIKit AlertController writing this code on an action in a swifui class

 var body: some View {
        Button(action:{
               NotificationCenter.default.post(name: Notification.Name("showAlert"), object: "Ελέγξτε το δίκτυο σας και προσπαθήστε αργότερα.")
 }
}

I'm using extension of UIViewController to get current vc and UIAlertController to present 'Alert'. Maybe you can try this as followings:

extension for UIViewController

extension UIViewController {
class func getCurrentVC() -> UIViewController? {
var result: UIViewController?
var window = UIApplication.shared.windows.first { $0.isKeyWindow }
        if window?.windowLevel != UIWindow.Level.normal {
            let windows = UIApplication.shared.windows
            for tmpWin in windows {
                if tmpWin.windowLevel == UIWindow.Level.normal {
                    window = tmpWin
                    break
                }
            }
        }
        let fromView = window?.subviews[0]
        if let nextRespnder = fromView?.next {
            if nextRespnder.isKind(of: UIViewController.self) {
                result = nextRespnder as? UIViewController
                result?.navigationController?.pushViewController(result!, animated: false)
            } else {
                result = window?.rootViewController
            }
        }
        return result
    }
}

extension for UIAlertController

extension UIAlertController {
    //Setting our Alert ViewController, presenting it.
    func presentAlert() {
        ViewController.getCurrentVC()?.present(self, animated: true, completion: nil)
    }

    func dismissAlert() {
        ViewController.getCurrentVC()?.dismiss(animated: true, completion: nil)
    }
}

And you can create your showAlert function now

func showMyAlert() {
let myAlert = UIAlertController(title: "Confirm order", message: "Are you sure to order two box of chocolate?", preferredStyle: .alert)
let okAction = UIAlertAction(title: "Ok!", style: .default) { (_) in
print("You just confirm your order")
} 
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in
print(You cancel it already!)
}
myAlert.addAction(okAction)
myAlert.addAction(cancelAction)
myAlert.presentAlert()
}

Wish my answer can help you. :-)

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