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?
4 Answers
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") 3I'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. :-)
1You 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: "Ελέγξτε το δίκτυο σας και προσπαθήστε αργότερα.") } }