Present UIAlertController from AppDelegate


转自:http://stackoverflow.com/questions/26952061/present-uialertcontroller-from-appdelegate



I'm trying to present a UIAlertController from the AppDelegate in my iOS app. Below is the alert and the present method.

UIAlertController *alert = [UIAlertController alertControllerWithTitle:cTitle message:cMessage preferredStyle:UIAlertControllerStyleAlert];

//Configure alert and actions

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

However, when I try to present the alert, it doesn't appear and I get the following alert in the console.

Warning: Attempt to present <UIAlertController: 0x145f5d60> on <UINavigationController: 0x146590f0> whose view is not in the window hierarchy!

What is causing the error and how do I fix it?

share improve this question
 
 
Trying to present right as the app is launching I'm guessing? –  Acey  Nov 16 '14 at 0:33 
 
Can you try this link for usefull Link: [ alertViewController](stackoverflow.com/a/37029075/2442762) –  joel prithivi  May 4 at 13:25 

8 Answers

You can use this code as well if you want to launch it from didFinishLaunchingWithOptions.Hope this helps.

dispatch_async(dispatch_get_main_queue(), {
              let importantAlert: UIAlertController = UIAlertController(title: "Action Sheet", message: "Hello I was presented from appdelegate ;)", preferredStyle: .ActionSheet)
            self.window?.rootViewController?.presentViewController(importantAlert, animated: true, completion: nil)
        })
share improve this answer
 
 
Hi @AdiQuadCore, your is useful only in swift application. In objC, the UIAlertController needs a pointer to the current UIViewController. –  Zeb  Sep 16 '15 at 12:22
 
This worked for me in ObjC in didFinishLaunchingWithOptions –  Seoras  Oct 6 at 5:04

you call it before the window is up and the navigationController is actually shown:

"Warning: Attempt to present on whose view is not in the window hierarchy!"

likely you do so in applicationDidFinishLaunching?


EITHER wait .. like do it when the view really appears

OR

one 'hack' would be to force the view and window up yourself:

[self.window addSubview:self.rootViewController.view];
[self.window makeKeyAndVisible];
share improve this answer
 

try this code..

-(void)application:(UIApplication *)application               didReceiveLocalNotification:(UILocalNotification *)notification
{
 NSLog(@"rakshapettu");
 UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"AlertView" message:@"I am an AlertView" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
                                                      handler:^(UIAlertAction * action) {
                                                          [alert dismissViewControllerAnimated:YES completion:nil];
                                                      }];
[alert addAction:defaultAction];
UIWindow *alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
alertWindow.rootViewController = [[UIViewController alloc] init];
alertWindow.windowLevel = UIWindowLevelAlert + 1;
[alertWindow makeKeyAndVisible];
[alertWindow.rootViewController presentViewController:alert animated:YES completion:nil]; 
}
share improve this answer
 

It's better to use something like:

var hostVC = self.window?.rootViewController

while let next = hostVC?.presentedViewController {
    hostVC = next
}

hostVC?.presentViewController(alertController, animated: true, completion: nil)

Previous answers won't work if you are already presenting modal view controller.

share improve this answer
 
 
Perfect answer and a really good method to handle modally presented view controllers! Thanks! –  NerdyTherapist  2 days ago

I was trying the same but does not work because after change of viewcontroller still returned the initial viewcontroller and throw the error whose view is not in the window hierarchy!. Finally, I found the solution to this problem:

UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)

But I have to force view controllers to update de keyWindow with this:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    UIApplication.sharedApplication().keyWindow!.rootViewController = self
    UIApplication.sharedApplication().keyWindow!.makeKeyAndVisible()
}
share improve this answer
 

You can try calling it in viewDidAppear instead of viewDidLoad. I had a similar error and that fixed it.

share improve this answer
 

Using Alert Controller:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
dispatch_async(dispatch_get_main_queue(), {

    //INTERNET NOT AVAILABLE ALERT
    var internetUnavailableAlertController = UIAlertController (title: "Network Unavailable", message: "Please check your internet connection settings and turn on Network Connection", preferredStyle: .Alert)

    var settingsAction = UIAlertAction(title: "Settings", style: .Default) { (_) -> Void in
        let settingsUrl = NSURL(string: UIApplicationOpenSettingsURLString)
        if let url = settingsUrl {
            UIApplication.sharedApplication().openURL(url)
        }
    }
    var cancelAction = UIAlertAction(title: "Okay", style: .Default, handler: nil)
    internetUnavailableAlertController .addAction(settingsAction)
    internetUnavailableAlertController .addAction(cancelAction)
    self.window?.rootViewController!.presentViewController(internetUnavailableAlertController , animated: true, completion: nil)
    })

Using AlertView:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    dispatch_async(dispatch_get_main_queue(), {

        //INTERNET NOT AVAILABLE ALERTVIEW

        let internetUnavailableAlert =  UIAlertView(title: "Network Unavailable", message: "Please check your internet connection settings and turn on Network Connection", delegate: self, cancelButtonTitle: "Okay")
        internetUnavailableAlert.show()
        })

  return true
 }
}
share improve this answer
 

You are trying to present UIAlertController on UINavigationController, which appeared to be your rootViewController and the problem is you cannot present UIAlertController on UINavigationController, the UIAlertController needs a view controller's from which it can be presented.

Can you not call as follow,

[self presentViewController:alert animated:YES completion:nil];

here self refers to current view controller, on which you are presenting the alert.

share improve this answer
 
 
thats not really what the message says though. and a navigationController is a viewController and it also has a view IF visible –  Daij-Djan  Nov 16 '14 at 0:44
 
Correct me if I am wrong, the UINavigationController class implements a specialized view controller that manages the navigation of hierarchical content so you cannot present any UIAlertController from it? –  ldindu Nov 16 '14 at 0:52

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 `AppDelegate` 中也可以使用 `UINavigationController` 进行页面的跳转,但是这不是一个好的编程实践,因为 `AppDelegate` 主要负责应用程序的生命周期和应用级别的事件处理,不应该直接处理视图控制器的跳转逻辑。 如果需要在 `AppDelegate` 中进行页面跳转,可以通过获取 `UIWindow` 的 `rootViewController` 属性来获取当前的根视图控制器,然后进行跳转。例如: ```objective-c - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 创建 UIWindow 实例 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; // 创建根视图控制器 UIViewController *rootViewController = [[UIViewController alloc] init]; rootViewController.view.backgroundColor = [UIColor whiteColor]; // 创建 UINavigationController 实例,并设置根视图控制器 UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController]; // 将 UINavigationController 实例设置为 UIWindow 的根视图控制器 self.window.rootViewController = navigationController; // 显示窗口 [self.window makeKeyAndVisible]; // 在需要的地方进行页面跳转 UIViewController *targetViewController = [[UIViewController alloc] init]; [navigationController pushViewController:targetViewController animated:YES]; return YES; } ``` 这样做虽然可以实现页面的跳转,但是建议还是在视图控制器中进行页面跳转,这样代码更加清晰,也符合 MVC 设计模式的思想。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值