Reputation: 403
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
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
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
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
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
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
Reputation: 965
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
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
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