<UINavigationController: 0xa98e050> 的开始/结束外观转换调用不平衡。

22

编译代码时出现警告:

"未平衡调用开始/结束外观转换:<UINavigationController: 0xa98e050>"

这是我的代码:

KVPasscodeViewController *passcodeController = [[KVPasscodeViewController alloc] init];
passcodeController.delegate = self;

UINavigationController *passcodeNavigationController = [[UINavigationController alloc] initWithRootViewController:passcodeController];
[(UIViewController *)self.delegate presentModalViewController:passcodeNavigationController animated:YES];
5个回答

63

我知道这是一个老问题,但为了那些再次遇到此问题的人,请看我找到的答案。

首先,问题没有说明在哪里调用了新的viewController
我怀疑这是从-(void)viewDidLoad中调用的。

将适当的代码移至-(void)viewDidAppear:中,问题就应该解决了。

这是因为在-viewDidLoad时,视图已经被加载,但尚未呈现,动画和视图也还未完成。

如果您打算推送一个窗口,请在窗口呈现并绘制后再执行操作。

如果您发现自己使用定时器来控制系统行为,请问自己您做错了什么或者如何更加正确地实现它。


这对我来说是正确的答案,而且用简单的语言解释了正在发生的事情。我之前也做过同样的事情,在上一个视图的动画完成之前以模态方式呈现了一个视图。 - Sententia
@Mark Travis:在我的情况下,我无法从'viewDidAppear'中调用。我正在使用ContainerViewClass,并根据某些操作切换视图控制器。这个警告消息总是出现。http://stackoverflow.com/questions/27632106/unbalanced-calls-to-begin-end-appearance-transitions-for-while-containerview-sw - Vineesh TP
这是正确的解决方案,甚至在至少一个苹果演示中都被发现是必需的,即MyImagePicker,其中错误消息ViewController会导致此类警告。 - drew..
我确实是在 viewDidLoad 中调用它,将那段代码移到 viewDidAppear 中解决了这个问题。这是正确的答案。 - Isuru
使用Xcode 9.1和Swift 4以及无故事板项目(我一切都是通过编程完成的),即使我从ViewDidAppear中呈现了一个viewController,我也遇到了问题。通过将所呈现控制器的ViewDidLoad代码插入异步块中解决了这个问题。 DispatchQueue.main.asyncAfter(deadline: when) {}。 - David Kramf

18

我发现如果你在之前的过渡(动画)仍然进行时尝试推新的视图控制器,就会出现这个问题。

无论如何,我认为这是presentModalViewController的问题,设置 animated:NO可能会解决你的问题

[(UIViewController *)self.delegate presentModalViewController:passcodeNavigationController animated:NO];

其他选项是:

使用NSTimer,在0.50到1秒之间调用上面的代码。这也是一个有用的技巧,可以确保您先前的视图控制器完成其动画。


2
是的,我尝试引入一个计时器;我只是认为这是一种hack方法,但如果这是被接受的解决方案...我担心我的代码在根本上有问题,也就是说,我没有按照传统的苹果方式来做,因此出现了错误。 - user798719
如果有“更好的方法”,为什么不在这里具体说明呢,Andreas?你的评论现在并没有建设性。 - wuf810

11

在之前的一个视图控制器的动画没有完成时,尝试加载新视图控制器会出现此警告。如果您的意图是这样做,只需将代码添加到 dispatch_async(dispatch_get_main_queue() 块中:

dispatch_async(dispatch_get_main_queue(), ^(void){
        [(UIViewController *)self.delegate presentModalViewController:passcodeNavigationController animated:YES];
});

警告将会消失。


3
一种现代化的解决方案可能是这样的:
double delayInSeconds = 0.5;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds *   NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [self.window.rootViewController presentViewController:yourVC animated:YES completion:nil];
});

1
你没有提供太多的上下文,所以我假设这个错误是在启动时发生的,因为你正在呈现一个密码视图控制器。
为了摆脱这个警告,我将应用程序委托注册为导航根视图控制器的委托:
- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ((UINavigationController *)self.window.rootViewController).delegate = self;
    return YES;
}

然后我在 navigationController:didShowViewController:animated: 中使用 dispatch_once 显示模态视图控制器:

- (void) navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        KVPasscodeViewController *passcodeController = [[KVPasscodeViewController alloc] init];
        passcodeController.delegate = self;

        UINavigationController *passcodeNavigationController = [[UINavigationController alloc] initWithRootViewController:passcodeController];
        [(UIViewController *)self.delegate presentViewController:passcodeNavigationController animated:YES completion:nil];
    });
}

由于根视图控制器已经出现后,会调用navigationController:didShowViewController:animated:方法,因此不再出现Unbalanced calls to begin/end appearance transitions警告。

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