Display UIAlertController from UIView/NSObject class
Solution 1
It looks like you are currently (pre-iOS8) triggering an alert view from within your view object. That's pretty bad practice, as in general alerts should be triggered from actions and logic. And that code should live in controllers.
I suggest you refactor your current code to move the logic that triggers the alert to the correct controller, and then you can easily upgrade to iOS 8 by using self
as the controller.
If instead you're calling the alert from an outside object, then pass in the controller to the method that calls the alert. Somewhere upstream you must have knowledge of the controller.
Solution 2
I solved an essentially similar problem today. Like Jageen, I ran into a situation where I wanted to present a UIAlertController but from a non-UIViewController class. In my case, I wanted an alert to pop up when the failure block of a HTTP request is run.
This is what I used and unlike our friend here, it worked quite perfectly for me.
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(errorAlert, animated: true, completion: nil)
Solution 3
The better solution for UIView
classes is below
ObjectiveC
UIViewController *currentTopVC = [self currentTopViewController];
currentTopVC.presentViewController.........
- (UIViewController *)currentTopViewController
{
UIViewController *topVC = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
while (topVC.presentedViewController)
{
topVC = topVC.presentedViewController;
}
return topVC;
}
Swift
var topVC = UIApplication.sharedApplication().keyWindow?.rootViewController
while((topVC!.presentedViewController) != nil){
topVC = topVC!.presentedViewController
}
topVC?.presentViewController........
Solution 4
My solution is below:
Swift
class alert {
func msg(message: String, title: String = "")
{
let alertView = UIAlertController(title: title, message: message, preferredStyle: .Alert)
alertView.addAction(UIAlertAction(title: "Done", style: .Default, handler: nil))
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alertView, animated: true, completion: nil)
}
}
Here is sample usage:
let Alert = alert()
Alert.msg("My alert (without title)")
Alert.msg("This is my alert", title: "Warning!")
Solution 5
For Swift 4
UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: true, completion: nil)
For Swift 5
UIApplication.shared.windows.last?.rootViewController?.present(alert, animated: true)
Related videos on Youtube
Jageen
Who AM I ? I am a digital player in this analog world. Github :- https://github.com/Jageen Hackerank :- https://www.hackerrank.com/JageenShukla Contact EmailID :- [email protected]
Updated on May 31, 2020Comments
-
Jageen about 4 years
I have
working iOS application
In order tosupport iOS8
, I am replacingUIAlertView/UIActionSheet with UIAlertController
.Problem :
For display UIAlertController I need presentViewController method of UIViewController class.
But UIAlertView is display from classes which areinherited
fromUIView or NSObject
,
I can not get[self presentViewController...]
method for obvious reason.My Work :
I tried getting rootViewController form current window and display UIAlertController.[[[UIApplication sharedApplication] keyWindow].rootViewController presentViewController ...]
but have some rotation problems like if my current view controller do not have rotation support it will rotate if UIAlertController is open.
Question :
Did any one faced same problem and have safe solution ?
if yes please provide me some example or give some guide-
nvrtd frst over 9 yearsI have had this problem. See my SO answer here for the code to get the topmost view controller with which to present another view controller. I agree that for most cases it is bad practice to present a view controller from an object that is not a view controller, but sometimes you DO need to.
-
-
Jageen almost 10 years+1 for suggestion, you are right, place for calling UIAlertView is wrong but, in current state i can not refactor it, i found same problem in many place, waiting for suggestion with less modification, any ways thanks, will apply your logic if no other suggestion came.
-
Dinesh Raja almost 9 yearsPreviously,
UIAlertView
has been working from anyUIView
orNSObject
. For ex: Showing alert fromUITableViewCell
works. There is no need to show it fromUIViewController
instance. Now,UIAlertController
presents only fromUIViewController
which is not easy to show alerts from cells. -
Jonny over 8 years"in general alerts should be triggered from actions and logic. And that code should live in controllers." - I prefer to put my business logic away from the (view) controllers, in my model. The controllers should only handle the visual side of the views they... control. So this all just doesn't make sense.
-
Rikkles over 8 years@Jonny business logic lives in business classes, but display logic lives in display controllers. When a display controller calls business logic that returns an error, it is up to it to determine how to display it to the user. I hope that makes it clearer.
-
LevinsonTechnologies over 8 yearsThanks. However what do you think about what Rikkles said above? That your paradigm is really broken?
-
Evgeny Aleksandrov about 8 yearsThis will not work when
rootViewController
is already presenting something else. -
rob123 about 8 yearsThis is great - but I found that I could do it a bit more simply: in my AlertViewController i simply added this code:
UIViewController *topVC = [[[[UIApplication sharedApplication] delegate] window] rootViewController]; [topVC presentViewController:presentUpdatedDataAvailableAlert animated:YES completion:nil];
-
Bill almost 8 yearsThis is a no-op for me.