ios 如何从 Appdelegate 显示 UIAlertController

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36155769/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 08:44:28  来源:igfitidea点击:

How to show UIAlertController from Appdelegate

iosobjective-ciphoneswift3uialertcontroller

提问by Rockers23

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

我正在 iOS 应用程序上使用 PushNotification。我想在应用程序收到通知时显示 UIalertcontroller。

I try this code below in the AppDelegate:

我在 AppDelegate 中尝试以下代码:

[self.window.rootViewController presentViewController:alert animated:YES completion:nil];

But the UIAlertcontroller is showing in the root View (First screen) and for other uiviewcontroller i got warning or the app crashes.

但是 UIAlertcontroller 显示在根视图(第一个屏幕)中,对于其他 uiviewcontroller,我收到警告或应用程序崩溃。

回答by Anbu.Karthik

try this

尝试这个

Objective-C

目标-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

Swift3 及以上

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/

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

回答by Yash Bedi

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 AnywhereExample :

有了这个,您可以在任何地方显示警报或任何示例:

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 :

无需创建任何扩展或任何方法或任何内容,只需编写以上 3 行即可创建警报和演示用途:

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

That's it.! =)

就是这样。!=)

回答by Najam

Anbu.Karthik's answerbut in Swift 4.1

Anbu.Karthik 的回答但在 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.

感谢您阅读本文。

回答by Rahul Panzade

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

Swift 4.1 您可以使用以下代码来显示来自 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)
    }
}

回答by Lal Krishna

For the easiness, I used category

为方便起见,我使用了类别

UIAlertController+UIWindow.h

UIAlertController+UIWindow.h

@interface UIAlertController (UIWindow)

- (void)show;
- (void)show:(BOOL)animated;

@end

UIAlertController+UIWindow.m

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];

回答by Pramod More

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

我编写了一个静态类来使代码可在 swift 4 中重用,该类提供了用于显示警报的不同方法。

        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)
       }

    }