How to show an alert from another class in Swift?

前端 未结 3 508
我寻月下人不归
我寻月下人不归 2021-02-02 02:11

I have a main class, AddFriendsController, that runs the following line of code:

ErrorReporting.showMessage(\"Error\", msg: \"Could not add student          


        
相关标签:
3条回答
  • 2021-02-02 02:48

    You can create extension method for UIApplication (for example) which will return your topViewController:

    extension UIApplication {
    
        static func topViewController(base: UIViewController? = UIApplication.sharedApplication().delegate?.window??.rootViewController) -> UIViewController? {
            if let nav = base as? UINavigationController {
                return topViewController(nav.visibleViewController)
            }
            if let tab = base as? UITabBarController, selected = tab.selectedViewController {
                return topViewController(selected)
            }
            if let presented = base?.presentedViewController {
                return topViewController(presented)
            }
    
            return base
        }
    }
    

    And then your class will look like this:

    class ErrorReporting {
    
        static func showMessage(title: String, msg: String) {
            let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertControllerStyle.Alert)
            alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil))
            UIApplication.topViewController()?.presentViewController(alert, animated: true, completion: nil)
        }
    }
    

    Method need to be static to be able to call it as ErrorReporting.showMessage.

    0 讨论(0)
  • 2021-02-02 02:48

    Swift 3 version of Maksym Musiienko's answer would be the following:

    extension UIApplication {
    
        static func topViewController(base: UIViewController? = UIApplication.shared.delegate?.window??.rootViewController) -> UIViewController? {
    
            if let nav = base as? UINavigationController {
                return topViewController(base: nav.visibleViewController)
            }
    
            if let tab = base as? UITabBarController, let selected = tab.selectedViewController {
                return topViewController(base: selected)
            }
    
            if let presented = base?.presentedViewController {
                return topViewController(base: presented)
            }
    
            return base
        }
    }
    
    0 讨论(0)
  • 2021-02-02 03:09

    Actually, in my opinion the view controller presenting operation should be done on the UIViewController instance, not in a model class.

    A simple workaround for it is to pass the UIViewController instance as a parameter

    class ErrorReporting {
        func showMessage(title: String, msg: String, `on` controller: UIViewController) {
            let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertControllerStyle.Alert)
            alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil))
            controller.presentViewController(alert, animated: true, completion: nil)
        }
    }
    

    And call it like below

    ErrorReporting.showMessage("Error", msg: "Could not add student to storage.", on: self)
    
    0 讨论(0)
提交回复
热议问题