警告:试图呈现视图控制器,但其视图不在窗口层次结构中

31

在我的一个应用中,我从application didReceiveLocalNotification方法中调用了一个viewController。页面成功加载,但显示出一个警告:

 Warning: Attempt to present <blankPageViewController: 0x1fda5190> on 
 <ViewController: 0x1fd85330> whose view is not in the window hierarchy!

我的代码如下:

 -(void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {

    blankPageViewController *myView = [[blankPageViewController alloc] 
               initWithNibName:@"blankPageViewController" bundle: nil];
    myView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
    [self.viewController presentViewController:myView animated:NO completion:nil];  
}

当你调用didReceiveLocalNotification方法时? - βhargavḯ
@Bhargavi: 这是一个当本地通知被接收时被调用的委托。 - Krishna Raj Salim
9个回答

21

最终我通过以下代码解决了那个问题。

-(void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
       self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
       self.blankviewController = [[blankPageViewController alloc] initWithNibName:@"blankPageViewController" bundle:nil];
       self.window.rootViewController = self.blankviewController;
       [self.window makeKeyAndVisible];
}

15

放置

[self.viewController presentViewController:myView animated:NO completion:nil];  

将其作为一个函数的参数,例如:

- (void)yourNewFunction
{
    [self.viewController presentViewController:myView animated:NO completion:nil];
}

然后像这样调用它:

[self performSelector:@selector(yourNewFunction) withObject:nil afterDelay:0.0];

问题在这里得到了说明,为什么performSelector:withObject:afterDelay会解决这个问题?因为选择器只有在下一次运行循环时才会被调用。所以事情有时间安定下来,你将只是跳过一个运行循环。


14

没错 x2:将我的 presentView 移动到 viewDidAppear 中解决了我的问题。 - xhinoda

2
我遇到了类似的问题。当应用程序进入前台时,我在AppDelegate.m中调用了presentViewController:方法:
- (void)applicationWillEnterForeground:(UIApplication *)application
{
    NSDate * lastActive = [[NSUserDefaults standardUserDefaults] objectForKey:@"lastActive"];

    double interval = [[NSDate date] timeIntervalSinceDate:lastActive];

    NSLog(@"Time Interval: %f", interval);

    if (interval > 900) { // interval is in seconds, so 900 seconds = 15 mins
        Login *pres = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:@"login"];

        UINavigationController *navi = ((UINavigationController*)self.window.rootViewController);
        if (navi.presentedViewController) {
            [navi dismissViewControllerAnimated:YES completion:^{
                [navi presentViewController:pres animated:NO completion:nil];
            }];
        } else {
            [navi presentViewController:pres animated:NO completion:nil];
        }
    }
}

如果在呈现登录视图控制器之前,该视图控制器已经存在,则此方法首先关闭该视图控制器(无论已推入哪些视图),然后再呈现登录视图控制器。否则,可以直接呈现登录视图控制器。


2
可能是因为当VC被呈现时,视图控制器的视图尚未加载到窗口层次结构中...
-(void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
    UINavigationController *navigationController = (UINavigationController*) self.window.rootViewController;
    rootViewController = [[navigationController viewControllers] objectAtIndex:0];
    blankPageViewController *myView = [[blankPageViewController alloc] initWithNibName:@"blankPageViewController" bundle: nil];
    [rootViewController presentModalViewController:myView animated:YES];
}

谢谢你的建议。我已经尝试过了。第一次它运行得很好,但如果通知再次出现,它会显示相同的警告...:( - Vinoy Alexander

1

特殊情况:

有些人可能通过谷歌找到这个问题,值得指出的是,如果您将一个未标记为故事板中初始视图的视图作为根视图控制器加载,并且加载了另一个视图,则有时会引发此错误。例如,在登录视图中,这些视图是从应用程序委托的applicationdidfinish...方法中以编程方式加载的。只需更改初始视图(在故事板中拖动箭头)为适合您层次结构的视图即可。虽然晦涩难懂,但值得指出。


0
针对Swift 2.0,我使用了viewDidAppear的覆盖方法:

let vc = self.storyboard?.instantiateViewControllerWithIdentifier("Second") as! SecondViewController

self.presentViewController(vc, animated: true, completion: nil)

其中,“Second”是在身份检查器中 SecondViewController 的故事板标识符。


0
I have used Navigation Controller and on which i have used a
ModalViewController to present a Popup(Present over current context). 
From this Popup i am opening a ViewController Modally which 
caused the Warning. So to resolve i did below change:

[self.presentedViewController performSegueWithIdentifier:@"PresentScreenSegueId" sender:sender];

0
如果您的应用程序类型为 UINavigationController,则可以使用此功能。
-(void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {

blankPageViewController *myView = [[blankPageViewController alloc]
                                   initWithNibName:@"blankPageViewController" bundle: nil];
myView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.navigationController presentViewController:myView animated:NO completion:nil]; }

希望这能对你有所帮助。 祝一切顺利!!!


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