在AppDelegate中显示UIAlertController

36

我想在我的iOS应用程序的AppDelegate中显示一个UIAlertController。 以下是警报和present方法。

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

//Configure alert and actions

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

然而,当我尝试展示警告时,它没有出现,而我在控制台中得到了以下警告。

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

什么导致了这个错误,我该怎么修复它?


你是在启动应用程序时尝试呈现正确的内容吗? - Acey
你可以尝试使用这个链接查看有用的内容:alertViewController - joel prithivi
7个回答

32

如果您想从didFinishLaunchingWithOptions启动此代码,也可以使用此代码。希望这可以帮助到你。

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

并且是最新的:

DispatchQueue.main.async {
    let alert = UIAlertController(title: "Hello!", message: "Greetings from AppDelegate.", preferredStyle: .alert)
    self.window?.rootViewController?.present(alert, animated: true, completion: nil)
}

嗨@AdiQuadCore,你的代码只适用于Swift应用程序。在ObjC中,UIAlertController需要指向当前UIViewController的指针。 - Zeb
1
这个在 ObjC 中的 didFinishLaunchingWithOptions 对我有用。 - Seoras

20

试试这段代码...

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

UIWindow是如何释放的? - meaning-matters

13

最好使用类似以下的内容:

var hostVC = self.window?.rootViewController

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

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

如果您已经显示了模态视图控制器,则以前的答案将不起作用。


完美的答案和一个处理模态呈现视图控制器的好方法!谢谢! - NerdyTherapist

5

当窗口还没有弹出,导航控制器尚未显示时,您就调用它:

"警告:试图在未在窗口层次结构中的视图上呈现!"

可能您在applicationDidFinishLaunching中这样做了?


要么等待......直到视图真正出现

要么

一个“hack”的方法是自己强制将视图和窗口弹出:

[self.window addSubview:self.rootViewController.view];
[self.window makeKeyAndVisible];

如果您不是在创建新窗口,那么您是否仍然需要执行makeKeyAndVisible操作?对于由AppDelegate提供的窗口,默认情况下不是已经发生了吗? - mfaani
一般来说:是的,但这对于提问者的问题来说太晚了。 - Daij-Djan
我有点困惑。你说的“太晚了”是什么意思?你的代码正确吗? - mfaani
我的答案对于给定的问题是正确的 :) 这里需要使用 makeKeyAndVisible。 - Daij-Djan

3

我也尝试过同样的方法,但是不起作用。因为在切换了视图控制器之后,仍然返回到了最初的视图控制器,并抛出了错误whose view is not in the window hierarchy!。最终,我找到了解决这个问题的方法:

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

但是我必须使用以下代码强制视图控制器更新 keyWindow

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

你真的不应该这样做。 - Rafael Nobre

1
你可以试着在viewDidAppear中调用它,而不是在viewDidLoad中调用。我也遇到了类似的错误,并且这样解决了它。

0

使用警告控制器:

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

使用 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
 }
}

UIAlertView现在已经被弃用。 - Colin Basnett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接