<UIViewController>的开始/结束外观转换调用不平衡。

3
根据苹果文档,我提出了以下在包容性控制器中切换控制器的方法。当有oldC时,控制台会显示Unbalanced calls to begin/end appearance transitions for <...>错误信息。请注意保留HTML标记。
- (void) showController:(UIViewController*)newC withView:(UIView*)contentView animated:(BOOL)animated
{
    UIViewController *oldC = self.childViewControllers.firstObject;
    if (oldC == newC) {
        return;
    }

    [oldC willMoveToParentViewController:nil];

    [self addChildViewController:newC];
    newC.view.frame = (CGRect){ 0, 0, contentView.frame.size };
    [contentView addSubview:newC.view];

    if (animated && oldC != nil) {
        oldC.view.alpha = 1.0f;
        newC.view.alpha = 0.0f;
        [self transitionFromViewController:oldC toViewController:newC duration:0.25f options:0 animations:^{

            oldC.view.alpha = 0.0f;
            newC.view.alpha = 1.0f;

         } completion:^(BOOL finished) {
            [oldC removeFromParentViewController];
            [newC didMoveToParentViewController:self];
         }];
    } else {
        oldC.view.alpha = 0.0f;
        newC.view.alpha = 1.0f;
        [oldC removeFromParentViewController];
        [newC didMoveToParentViewController:self];
    }
}

这是我称之为的方式:
- (IBAction) buttonSignIn:(id)sender
{
    [self showController:self.signInViewController withView:self.contentView animated:(sender != nil)];
}

- (IBAction) buttonSignUp:(id)sender
{
    [self showController:self.signUpViewController withView:self.contentView animated:(sender != nil)];
}

为了追踪这个问题,我正在记录外观转换。
-(void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated
{
    [super beginAppearanceTransition:isAppearing animated:animated];
    NSLog(@"**begin %@", self);
}

-(void)endAppearanceTransition
{
    [super endAppearanceTransition];
    NSLog(@"**end** %@", self);
}

这是日志的样子:
] **begin <SignInViewController: 0x10c769a20>
] **begin <SignUpViewController: 0x10c768770>
] Unbalanced calls to begin/end appearance transitions for <SignUpViewController: 0x10c768770>.
] **end** <SignUpViewController: 0x10c768770>
] **end** <SignInViewController: 0x10c769a20>

现在我有点困惑。这里的问题是什么?

3个回答

16

结果发现transitionFromViewController:toViewController:duration:options:animations:completion:也会添加视图。

该方法将第二个视图控制器的视图添加到视图层次结构中,然后执行在动画块中定义的动画。 动画完成后,它将从视图层次结构中删除第一个视图控制器的视图。

这意味着addSubview需要相应地进行调整。

- (void) showController:(UIViewController*)newC withView:(UIView*)contentView animated:(BOOL)animated
{
    UIViewController *oldC = self.childViewControllers.firstObject;
    if (oldC == newC) {
        return;
    }

    [oldC willMoveToParentViewController:nil];

    [self addChildViewController:newC];
    newC.view.frame = (CGRect){ 0, 0, contentView.frame.size };

    if (animated && oldC != nil) {
        oldC.view.alpha = 1.0f;
        newC.view.alpha = 0.0f;
        [self transitionFromViewController:oldC toViewController:newC duration:0.25f options:0 animations:^{

            oldC.view.alpha = 0.0f;
            newC.view.alpha = 1.0f;

         } completion:^(BOOL finished) {
            [oldC removeFromParentViewController];
            [newC didMoveToParentViewController:self];
         }];
    } else {
        [contentView addSubview:newC.view];
        oldC.view.alpha = 0.0f;
        newC.view.alpha = 1.0f;
        [oldC removeFromParentViewController];
        [newC didMoveToParentViewController:self];
    }
}

我尝试了tcurdt建议的一切。经过数小时的奋斗,我终于让它工作了。tcurdt,你真是个天才! - Ahmed Ahmedov
如果您不想进行动画,传递 duration:0 是安全的:https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/#//apple_ref/occ/instm/UIViewController/transitionFromViewController:toViewController:duration:options:animations:completion: - Heath Borders
谢谢,你救了我的一天。 - Dan

1

旧代码

[self addChildViewController:toVC];
[fromVC willMoveToParentViewController:nil];
[self.view addSubview:toVC.view];
[toVC.view mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.mas_equalTo(0);
 }];

 [self transitionFromViewController:fromVC
                      toViewController:toVC duration:0
                               options:UIViewAnimationOptionTransitionNone
                            animations:^{
                            } completion:^(BOOL finished) {
                                [fromVC.view removeFromSuperview];
                                [fromVC removeFromParentViewController];
                                [toVC didMoveToParentViewController:self];
                                self.currentVC = toVC;
                            }];

新代码,没问题。
[self addChildViewController:toVC];
[fromVC willMoveToParentViewController:nil];

    [self transitionFromViewController:fromVC
                      toViewController:toVC duration:0
                               options:UIViewAnimationOptionTransitionNone
                            animations:^{
                            } completion:^(BOOL finished) {
                                [fromVC.view removeFromSuperview];
                                [fromVC removeFromParentViewController];
                                [toVC didMoveToParentViewController:self];
                                self.currentVC = toVC;
                            }];

0
我将持续时间设置为0,这意味着在transitionFromViewController调用中使用animation:NO

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