How to show UIAlertController from Appdelegate

前端 未结 6 1717
后悔当初
后悔当初 2020-11-30 01:32

I\'m working with PushNotification on iOS app. I would like to show a UIalertcontroller when the app receive a notification.

I try this code below in the AppDelegate

相关标签:
6条回答
  • 2020-11-30 02:11

    For the easiness, I used category

    UIAlertController+UIWindow.h

    @interface UIAlertController (UIWindow)
    
    - (void)show;
    - (void)show:(BOOL)animated;
    
    @end
    

    UIAlertController+UIWindow.m

    #import <objc/runtime.h>
    
    @interface UIAlertController (Private)
    
    @property (nonatomic, strong) UIWindow *alertWindow;
    
    @end
    
    @implementation UIAlertController (Private)
    
    @dynamic alertWindow;
    
    - (void)setAlertWindow:(UIWindow *)alertWindow {
        objc_setAssociatedObject(self, @selector(alertWindow), alertWindow, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (UIWindow *)alertWindow {
        return objc_getAssociatedObject(self, @selector(alertWindow));
    }
    
    @end
    
    @implementation UIAlertController (UIWindow)
    
    - (void)show {
        [self show:YES];
    }
    
    - (void)show:(BOOL)animated {
        [self setupWindow];
        [self.alertWindow.rootViewController presentViewController:self animated:animated completion:nil];
    }
    
    - (void)setupWindow {
        self.alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        self.alertWindow.rootViewController = [[UIViewController alloc] init];
    
        id<UIApplicationDelegate> delegate = [UIApplication sharedApplication].delegate;
        if ([delegate respondsToSelector:@selector(window)]) {
            self.alertWindow.tintColor = delegate.window.tintColor;
        }
    
        UIWindow *topWindow = [UIApplication sharedApplication].windows.lastObject;
        self.alertWindow.windowLevel = topWindow.windowLevel + 1;
    
        [self.alertWindow makeKeyAndVisible];
    }
    
    - (void)viewDidDisappear:(BOOL)animated {
        [super viewDidDisappear:animated];
    
        // precaution to insure window gets destroyed
        self.alertWindow.hidden = YES;
        self.alertWindow = nil;
    }
    

    Use:

    UIAlertController *alertController;
    // -- code --
    [alertController show];
    
    0 讨论(0)
  • 2020-11-30 02:12

    try this

    Objective-C

    UIWindow* topWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    topWindow.rootViewController = [UIViewController new];
    topWindow.windowLevel = UIWindowLevelAlert + 1;
    
    UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"APNS" message:@"received Notification" preferredStyle:UIAlertControllerStyleAlert];
    
    [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK",@"confirm") style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        // continue your work
    
        // important to hide the window after work completed.
        // this also keeps a reference to the window until the action is invoked.
        topWindow.hidden = YES; // if you want to hide the topwindow then use this
        topWindow = nil; // if you want to remove the topwindow then use this 
    }]];
    
    [topWindow makeKeyAndVisible];
    [topWindow.rootViewController presentViewController:alert animated:YES completion:nil];
    

    Swift3 and above

    var topWindow: UIWindow? = UIWindow(frame: UIScreen.main.bounds)
    topWindow?.rootViewController = UIViewController()
    topWindow?.windowLevel = UIWindow.Level.alert + 1
    
    let alert = UIAlertController(title: "APNS", message: "received Notification", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "OK", style: .cancel) { _ in
        // continue your work
    
        // important to hide the window after work completed.
        // this also keeps a reference to the window until the action is invoked.
        topWindow?.isHidden = true // if you want to hide the topwindow then use this
        topWindow = nil // if you want to hide the topwindow then use this
     })
    
    topWindow?.makeKeyAndVisible()
    topWindow?.rootViewController?.present(alert, animated: true, completion: nil)
    

    Detail description: http://www.thecave.com/2015/09/28/how-to-present-an-alert-view-using-uialertcontroller-when-you-dont-have-a-view-controller/

    0 讨论(0)
  • 2020-11-30 02:15

    Shortest & Simplest :

    Create a extension :

    extension UIApplication {
    class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let navigationController = controller as? UINavigationController {
            return topViewController(controller: navigationController.visibleViewController)
        }
        if let tabController = controller as? UITabBarController {
            if let selected = tabController.selectedViewController {
                return topViewController(controller: selected)
            }
        }
        if let presented = controller?.presentedViewController {
            return topViewController(controller: presented)
        }
        return controller
    } }
    

    and then use it anywhere like

    UIApplication.topViewController()?.present(UIViewController, animated: true, completion: nil)
    

    With this you can present Alert or anything Anywhere Example :

    let alert = UIAlertController(title: "Your title", message: "Your message", preferredStyle: .alert)
    let cancelButton = UIAlertAction(title: "Ok", style: .cancel, handler: nil)
    alert.addAction(cancelButton)
    UIApplication.topViewController()?.present(alert, animated: true, completion: nil)
    

    ALTERNATE METHOD :

    No need to create any Extension or any method or anything simply write the above 3 lines for creating an Alert and for presenting use :

    self.window?.rootViewController?.present(alert, animated: true, completion: nil)
    

    That's it.! =)

    0 讨论(0)
  • 2020-11-30 02:21

    I have written a static class to make code reusable in swift 4, This class provied different methods for showing alerts.

            class AlertUtility: NSObject {
    
            static func showAlert(title: String!, message : String!, viewController: UIViewController) {
                let alert = UIAlertController(title: title, message: message ,preferredStyle: UIAlertControllerStyle.alert)
    
                alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "ok"), style: UIAlertActionStyle.cancel, handler: nil))
    
                viewController.present(alert, animated: true, completion: nil)
            }
    
            static func showAlertAutoDismiss(title: String!, message : String!) -> Void {
                //let appDelegate = UIApplication.shared.delegate as! AppDelegate
    
                // the alert view
                let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
    
                let topWindow = UIWindow(frame: UIScreen.main.bounds)
                topWindow.rootViewController = UIViewController()
                topWindow.windowLevel = UIWindowLevelAlert + 0.8
    
                topWindow.makeKeyAndVisible()
                topWindow.rootViewController?.present(alert, animated: true, completion: {})
    
                // change to desired number of seconds (in this case 5 seconds)
                let when = DispatchTime.now() + 1
                DispatchQueue.main.asyncAfter(deadline: when){
                    // your code with delay
                    alert.dismiss(animated: true, completion: nil)
                    topWindow.isHidden = true
                }
            }
    
            // Show alert view with call back
            static func showAlertWithCB(title: String, message: String, isConditional: Bool, viewController: UIViewController, completionBlock: @escaping (_: Bool) -> Void) {
    
                let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
    
                // Check whether it's conditional or not ('YES' 'NO, or just 'OK')
                if isConditional
                {
                    alert.addAction(UIAlertAction(title: NSLocalizedString("yes", comment: ""), style: UIAlertActionStyle.default, handler: { (action: UIAlertAction) in
                        alert.dismiss(animated: true, completion: nil)
                        completionBlock(true)
                    }))
    
                    alert.addAction(UIAlertAction(title: NSLocalizedString("no", comment: ""), style: UIAlertActionStyle.default, handler: { (action: UIAlertAction) in
                        alert.dismiss(animated: true, completion: nil)
                        completionBlock(false)
                    }))
                }
                else
                {
                    alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "ok"), style: UIAlertActionStyle.default, handler: { (action: UIAlertAction) in
                        alert.dismiss(animated: true, completion: nil)
                        completionBlock(true)
                    }))
                }
    
                viewController.present(alert, animated: true, completion: nil)
            }
    
            static func showAlert(title: String!, message : String!) -> Void {
                //let appDelegate = UIApplication.shared.delegate as! AppDelegate
    
                // the alert view
                let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
    
                let topWindow = UIWindow(frame: UIScreen.main.bounds)
                topWindow.rootViewController = UIViewController()
                topWindow.windowLevel = UIWindowLevelAlert + 1
                topWindow.makeKeyAndVisible()
                topWindow.rootViewController?.present(alert, animated: true, completion: {})
    
                alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "ok"), style: UIAlertActionStyle.cancel, handler: {(_ action: UIAlertAction) -> Void in
                    // continue your work
                    // important to hide the window after work completed.
                    // this also keeps a reference to the window until the action is invoked.
                    topWindow.isHidden = true
                }))
    
            }
    
            static func showComingSoon(viewController: UIViewController) {
                let alert = UIAlertController(title: "", message: "Coming Soon", preferredStyle: .alert)
    
                viewController.present(alert, animated: true, completion: {})
    
                // change to desired number of seconds (in this case 1 seconds)
                let when = DispatchTime.now() + 0.6
                DispatchQueue.main.asyncAfter(deadline: when){
                    // your code with delay
                    alert.dismiss(animated: true, completion: nil)
                }
            }
    
            static func showGenericErrorMessageAlert(viewController: UIViewController) {
                let alert = UIAlertController(title: NSLocalizedString("error", comment: ""), message: NSLocalizedString("generic.error.message", comment: "") ,preferredStyle: UIAlertControllerStyle.alert)
    
                alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "ok"), style: UIAlertActionStyle.cancel, handler: nil))
    
                viewController.present(alert, animated: true, completion: nil)
            }
    
     static func showAlertWithTextField(viewController : UIViewController,completionBlock: @escaping (_: Bool, String) -> Void) {
    
            //1. Create the alert controller.
            let alert = UIAlertController(title: "Report Event?", message: "", preferredStyle: .alert)
            alert.view.tintColor = APP_ORANGE_COLOR
            //2. Add the text field. You can configure it however you need.
            //AlertUtility.addte
            alert.addTextField { (textField) in
    
                let heightConstraint = NSLayoutConstraint(item: textField, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 50)
                textField.addConstraint(heightConstraint)
                textField.placeholder = "Enter report reason here"
                textField.tintColor = APP_ORANGE_COLOR
                textField.autocapitalizationType = .sentences
            }
    
            // 3. Grab the value from the text field, and print it when the user clicks OK.
            alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (_) in
                // Force unwrapping because we know it exists.
                completionBlock(true,"")
                //print("Text field: \(textField.text)")
            }))
    
            // 3. Grab the value from the text field, and print it when the user clicks OK.
            alert.addAction(UIAlertAction(title: "Submit", style: .default, handler: { [weak alert] (_) in
                let textField = alert?.textFields![0] // Force unwrapping because we know it exists.
                completionBlock(true,(textField?.text)!)
                //print("Text field: \(textField.text)")
            }))
    
            // 4. Present the alert.
            viewController.present(alert, animated: true, completion: nil)
    
            let textField = alert.textFields![0]
            let v = UIView.init(frame: textField.frame)
            textField.addSubview(v)
            v.frame = textField.frame
            v.bounds = textField.bounds
            v.backgroundColor = APP_ORANGE_COLOR
            v.superview?.bringSubview(toFront: v)
           }
    
        }
    
    0 讨论(0)
  • 2020-11-30 02:31

    Anbu.Karthik's answer but in Swift 4.1

    var topWindow: UIWindow? = UIWindow(frame: UIScreen.main.bounds)
    topWindow?.rootViewController = UIViewController()
    topWindow?.windowLevel = UIWindowLevelAlert + 1
    let alert: UIAlertController =  UIAlertController(title: "APNS", message: "received Notification", preferredStyle: .alert)
        alert.addAction(UIAlertAction.init(title: "OK", style: .default, handler: { (alertAction) in
            topWindow?.isHidden = true
            topWindow = nil
        }))
    
    topWindow?.makeKeyAndVisible()
    topWindow?.rootViewController?.present(alert, animated: true, completion:nil)
    

    Thanks for reading this.

    0 讨论(0)
  • 2020-11-30 02:34

    Swift 4.1 You can use the following code to present alert from AppDelegate

    func showAlertFromAppDelegates(){
        let alertVC = UIAlertController(title: "Oops" , message: "Presented Alert from AppDelegates", preferredStyle: UIAlertControllerStyle.alert)
        let okAction = UIAlertAction(title: "Okay", style: UIAlertActionStyle.cancel) { (alert) in
            exit(0) // Your code here
        }
        alertVC.addAction(okAction)
        DispatchQueue.main.async {
            var presentVC = self.window?.rootViewController
            while let next = presentVC?.presentedViewController {
                presentVC = next
            }
            presentVC?.present(alertVC, animated: true, completion: nil)
        }
    }
    
    0 讨论(0)
提交回复
热议问题