iOS 7 - 在呈现模态视图控制器时收到警告消息

23

在使用iOS7编译和运行时,当我呈现模态视图控制器时,会出现警告消息:“不建议在分离的视图控制器上显示视图控制器”。在使用iOS6或更早版本时,我从未遇到过此问题。是否有人能够展示一下,在呈现模态视图控制器时是否有任何变化?

SearchViewController *controller1;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
    controller1 = [[SearchViewController alloc] initWithNibName:@"SearchViewController-iPad" bundle:nil];
}
else
{
   controller1 = [[SearchViewController alloc] initWithNibName:@"SearchViewController" bundle:nil];
}
controller1.delegate = self;
[[self navigationController] presentModalViewController:controller1 animated:YES];

*编辑 * 这是代码,请问嵌套在哪里。看起来它们是嵌套的,请建议如何使用子视图控制器模式进行链接。

(void)applicationDidFinishLaunching:(UIApplication *)application
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
    {
        self.loginRootviewController =   [[MainViewController alloc] initWithNibName:@"MainViewController-iPad" bundle:nil];
    }
    else
    {
       self.loginRootviewController =   [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
    }

    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.loginRootviewController];


    DDMenuController *rootController = [[DDMenuController alloc] initWithRootViewController:navController];
    _menuController = rootController;



    AppMainMenuViewController *leftController = [[AppMainMenuViewController alloc] init];
    rootController.leftViewController = leftController;
    self.loginRootviewController.delegateLogin = leftController;

    self.window.rootViewController = rootController;

    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];

}

4
顺便说一下,presentModalViewController:animated: 方法已经过时了,你应该使用新的方法。 - rdelmar
3
自iOS 6.0起,presentModalViewController:animated:已被弃用,请使用presentViewController:animated:completion:代替。 - Sviatoslav Yakymiv
1
不要从导航控制器中呈现,而是从“self”呈现。UIKit 会处理这个问题,并找到最好的候选视图控制器来进行呈现。 - pronebird
11个回答

18

我遇到了同样的问题,而且我也没有使用Storyboard(我正在处理一个三年前的项目)。

在我的情况下,原因是我没有将我的应用程序的rootViewController指定给窗口,就像这样:

- (BOOL)application:didFinishLaunchingWithOptions:
{
    ...
    self.window.rootViewController = myRootViewController; // I was missing this
    ...
}

现在不再有警告。


1
通过我的应用程序获取消息,rootViewController已设置。 - Hot Licks
4
也许你正在使用一些嵌套的viewControllers。如果是这种情况,任何嵌套的viewController都应该有一个parentViewController。如果使用标准容器视图控制器(例如UINavigationController),则这种父子关系是自动的,否则需要在代码中完成。请查看UIViewController文档中的"实现容器视图控制器"以获取更多详细信息。 - Riccardo Tesio
在我的情况下似乎没有实际的方法来设置parentViewController。 - Hot Licks

18

通常情况下,当我们尝试在不属于rootViewController的其他视图控制器中以模态方式呈现视图控制器并仅添加子视图控制器的视图时,就会出现此警告。

在这种情况下,我们应该在那个属于rootViewController的视图控制器中调用presentViewController。

因此,我们可以直接在rootViewController中呈现任何视图控制器。

UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
[vc presentViewController:obj animated:YES completion:nil];
[vc dismissViewControllerAnimated:YES completion:nil];

这个解决了我的问题。但是如果我们从根视图控制器呈现一个视图控制器,会有什么问题吗? - Vineeth
太好了,我一直收到这个警告,并且在应用程序处于后台时尝试显示闪屏时,SLComposeViewController出现了一些非常奇怪的UI问题。上述方法解决了所有问题。 - bmjohns

18

如果故事板与根视图控制器之间没有任何连线将视图控制器连接起来,那么该视图控制器就被分离。

建议您在使用故事板时,通过Interface Builder创建segue并在代码中调用它,即使是用于模态视图。

即使在XCode 4.6.x和iOS 6.x下,您也会在构建时收到有关未连接的视图控制器的警告。

如果您有两个故事板(一个用于iPhone,一个用于iPad),则可以为每个故事板命名相同的segue。 Segue标识符只需要在每个故事板中唯一即可。 因此,使用相同标识符执行Segue (performSegueWithIdentifier) 可以将您带到iPhone上的一个地方,而将另一个地方带到iPad上。


31
如果应用程序没有使用Storyboard,该怎么办? - Ram G.
5
我在 iOS 7 的 Xcode 5 中仍然收到警告。它在所有旧版本中都能正常工作。我现在可以忽略这个警告,但更大的问题是:1. 该视图无法旋转。2. 视图会被遮挡住状态栏。看起来更好的解决方案是将所有 xib 转换为 storyboard,并不支持任何早于 5.0 版本的操作系统。但在目前阶段,这需要付出太多的工作量。我正在使用其他的解决方法,例如使用 pushViewController 而不是 presentViewcontroller,并添加自定义动画。 - Ram G.
2
@SimonH 我正在使用DDMenuViewController。两者具有相同的功能。 - Ram G.
1
我正在遇到相同的错误,我没有使用Storyboard或nib。我的应用程序有导航控制器,我在使用presentviewcontroller来展示一些图片。 - Gagan Joshi
1
我有这个症状,而且该应用程序从未接近Storyboard。使用presentViewController:animated:completion:presentModalViewController:animated:呈现MFMailComposeViewController时出现此消息。 - Hot Licks
显示剩余13条评论

7

对于使用DDMenuViewController的用户,这是一个简单的解决方案。只需在initWithRootViewController中添加[self addChildViewController:controller];, 以及在setRightViewControllersetLeftViewController中添加即可。


我同意 - 根据我对当前标记为正确答案的评论。 - AppHandwerker

4
为了避免在推送导航中收到警告,您可以直接使用:
[self.view.window.rootViewController presentViewController:viewController animated:YES completion:nil];

接着,在您的模态视图控制器中,当所有操作完成后,您只需要调用:

[self dismissViewControllerAnimated:YES completion:nil];

该代码段可以帮助您退出当前模态视图。


是的,这在iOS7上可以工作,我刚刚在这里测试了 QLPreviewController *previewController = [[QLPreviewController alloc]init]; previewController.delegate = self; previewController.dataSource = self;[self.view.window.rootViewController presentViewController:previewController animated:YES completion:nil]; - Alejandro Luengo
尝试在iOS 8上使用以下代码:[self.view.window.rootViewController.navigationController pushViewController:YOUR_VIEW_CONTROLER animated:YES]; - Fede Cugliandolo

2

如果您正在使用Storyboard并遇到此错误,可能是因为在viewDidLoad中尝试过快自动呈现视图。如果您稍后一段时间调用模态segue,则可以正常工作而无需进一步警告。


3
只有在viewDidAppear之后,才能呈现任何内容。 - pronebird
原因很简单,当viewWillAppear被调用时,您的VC正在过渡中,而当viewDidLoad被触发时,它尚未在视图层次结构中。因此,呈现任何内容可能会导致UIKit发出警告、崩溃或不一致性。 - pronebird

2

如果您嵌套了视图控制器,则可能仍然会出现此消息。 如果是这种情况,请确保使用子视图控制器模式链接它们。


请查看我在问题主体部分上方的代码。看起来它们是嵌套的,请建议如何链接。 - Ram G.

1
在viewDidAppear中调用[self presentViewController:vc animated:NO completion:nil];解决了我的问题。

0
我发现,如果你正在使用故事板,你会想把呈现新视图控制器的代码放在viewDidAppear中。这也会消除“不平衡的调用开始/结束出现转换”的警告。

0

我曾经遇到过同样的问题。但与其说是我如何启动视图,不如说是视图的配置方式有误。我不小心将视图上的类设置为了视图控制器类,而不是文件所有者。线索在于它显示了视图,但某些样式却丢失了。奇怪的是,在旧版本的iOS上它还能正常工作。


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