knowledgeseeker
knowledgeseeker

Reputation: 403

Multiple UIAlertControllers in iOS

In my app there are scenarios where multiple alerts could come. But as in iOS8 UIAlertview turned to UIAlertController, i am not able to show multiple alerts as you can not present two or more controllers at the same time.

How can I achieve this using UIAlertController?

Upvotes: 12

Views: 12094

Answers (8)

Artem Sydorenko
Artem Sydorenko

Reputation: 382

You need to present it on a top presented controller, you can use this extension:

extension UIViewController {

    var topController: UIViewController {
        presentedViewController?.topController ?? self
    }
}
self.topController.present(alert, animated: true)

Upvotes: 1

AshvinGudaliya
AshvinGudaliya

Reputation: 3314

You can Find Top Most View Controller using this Function.

func topViewController(_ base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
    if let nav = base as? UINavigationController {
        return topViewController(nav.visibleViewController)
    }
    if let tab = base as? UITabBarController {
        if let selected = tab.selectedViewController {
            return topViewController(selected)
        }
    }
    if let presented = base?.presentedViewController {
        return topViewController(presented)
    }
    return base
}

Present UIAlertController Using this Method through. like,

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

Method Info: topViewController() find a top Most presented view controller, UIAlertController supper class is UIViewController.

first UIAlertController is open normal in top presented view controller, try to open a second UIAlertController then topViewController() given first alert view. so no any UIAlertController missed.

Upvotes: 0

Jitendra Singh
Jitendra Singh

Reputation: 2181

You can use JSAlertView which handles both UIAlertView and UIAlertController APIs.

It handles multiple alerts fired at same time, very well. It also provide super easy methods for displaying simple alerts.

Upvotes: 0

Brendan Lynch
Brendan Lynch

Reputation: 31

Swift version for @Bejibun's answer above:

    let alertView = UIAlertController(title: "New Message", message: "Message Body", preferredStyle: .Alert)

    alertView.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: { (UIAlertAction) in
       alertView.dismissViewControllerAnimated(true, completion: nil)
    }))

    let alertWindow = UIWindow(frame: UIScreen.mainScreen().bounds)
    alertWindow.rootViewController = UIViewController()
    alertWindow.windowLevel = UIWindowLevelAlert + 1
    alertWindow.makeKeyAndVisible()
    alertWindow.rootViewController?.presentViewController(alertView, animated: true, completion: nil)

Upvotes: 3

Kraming
Kraming

Reputation: 257

I think I am pretty late for this but still posting as It might be useful for someone looking for this though Apple doesn't recommend multiple alerts stacking thats why they deprecated this UIAlertView from to UIAlertController implementation.

I have created a AQAlertAction subclass for UIAlertAction. You can use it for staggering Alerts, the usage is same as you are using UIAlertAction. All you need to do is import AQMutiAlertFramework in your project or you can include class also (Please refer Sample project for that). Internally It uses binary semaphore for staggering the Alerts until user handle action associated with current alert displayed. Let me know if it works for you.

Upvotes: 0

Here is the method to show multiple alertControllers :

        UIAlertController *av = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];

        UIAlertAction *cancelAction = [UIAlertAction
                                       actionWithTitle:kAlertOk
                                       style:UIAlertActionStyleCancel
                                       handler:^(UIAlertAction *action)
                                       {

                                       }];
        [av addAction:cancelAction];

        UIWindow *alertWindow = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
        alertWindow.rootViewController = [[UIViewController alloc]init];
        alertWindow.windowLevel = UIWindowLevelAlert + 1;
        [alertWindow makeKeyAndVisible];
        [alertWindow.rootViewController presentViewController:av animated:YES completion:nil];

Upvotes: 9

Glorfindel
Glorfindel

Reputation: 22651

You can keep track of a list of alerts to show in your view controller as an instance variable, say

NSMutableArray *alertsToShow;

You can present the first UIAlertController, and add a UIAlertAction in which you present the next alert (if applicable), with a recursive-like method:

- (void)showAlertIfNecessary {
    if (alertsToShow.count == 0)
        return;

    NSString *alert = alertsToShow[0];
    [alertsToShow removeObjectAtIndex:0];

    UIAlertController *alertController = [UIAlertController
                          alertControllerWithTitle:@"Title"
                          message:alert
                          preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *okAction = [UIAlertAction 
        actionWithTitle:@"OK"
                  style:UIAlertActionStyleDefault
                handler:^(UIAlertAction *action)
                {
                    [self showAlertIfNecessary];
                }];
    [alertController addAction:okAction];
    [self presentViewController:alertController animated:YES completion:nil];
}

Note that this can get very annoying to the user, if he/she needs to click through a lot of messages. You might consider combining them into a single message.

Upvotes: 6

matt
matt

Reputation: 535925

You cannot show multiple alerts simultaneously, and if you were doing so before, you were behaving badly. Rethink your interface.

You can easily present alerts in succession, which is all you really need:

let alert = UIAlertController(title: "One", message: nil, preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "Next", style: .Default, handler: {
    _ in
    let alert2 = UIAlertController(title: "Two", message: nil, preferredStyle: .Alert)
    alert2.addAction(UIAlertAction(title: "OK", style: .Cancel, handler:nil))
    self.presentViewController(alert2, animated: true, completion: nil)
        }))
self.presentViewController(alert, animated: true, completion: nil)

Upvotes: 2

Related Questions