尝试在转场过程中解除演示控制器的显示

33

我使用Xcode6 GM在iOS8 GM上编译我的项目。当关闭许多视图控制器时,我的应用程序总是崩溃,并且调试区域显示:

"尝试在正在转换的同时解除表示控制器的绑定。 transitionViewForCurrentTransition未设置,表示控制器在演示期间被解除? "

我已经搜索过并找到一个类似的案例,并显示相同的错误:

[self.viewController presentViewController:vc animated:NO completion:^{
        [self.viewController dismissViewControllerAnimated:NO completion:nil];
}];

在使用Xcode5和iOS7时,它运行良好。那么这个错误是什么意思呢?iOS8不喜欢这个“Hack”吗?谢谢提前。


你想通过上述代码实现什么目标? - Midhun MP
我刚遇到了完全相同的错误.. - Jeef
我的假设是将视图强制为单一方向 - 这就是我正在做的事情,我遇到了相同的错误。 - Jeef
当关闭许多视图控制器时,如果我从前往后关闭它们,我的应用程序会崩溃,但是以相反的顺序(从后往前)关闭,则我的应用程序可以正常工作。 - ylovesy
4个回答

38

你是否试图强制设备方向改变?无论如何,在我看来,你可以尝试将当前的代码更改为:

[self.navigationController presentViewController:vc animated:NO completion:^{
    dispatch_after(0, dispatch_get_main_queue(), ^{
        [self.navigationController dismissViewControllerAnimated:NO completion:nil];
    });
}];

2
你可以直接在主队列上分派任务,而无需延迟。 - malex
有关这个的任何消息吗?如果您在多个类中有类似的实现,那么这是一个相当丑陋的黑客! - Matteo Lallone
1
在iOS8.1上,当使用Game Centre邀请视图时,dismissViewControllerAnimated开始崩溃。这个修复方法非常有效! - Danny Parker
这对我有用,供您参考。不过,找到导致错误的行号花费了很多时间。 - Alex Spencer
@malex - 至少在iOS 8.3中,那并不是完全正确的。由于某种奇怪的原因,您必须使用零延迟进行调度,以便通过此错误进行黑客攻击。这个错误非常古老,但苹果似乎并不关心。 - Radu Simionescu
太好了!非常感谢。 - echo

10

我曾经遇到过同样的问题,但是我找到了一个简洁的解决方案,避免使用dispatch_async或dispatch_after。

就像异常信息所描述的一样,你试图在呈现转换仍在进行时关闭视图控制器。

这意味着一旦

- presentViewController:animated:completion: 

当调用完成块并调用dismiss时,转换未完成。

从iOS 7开始,UIViewController有一个新的可用方法。

- transitionCoordinator 

transitionCoordinator可以在转场完成后立即将完成块加入队列。

该方法返回的对象符合UIViewControllerTransitionCoordinator协议。知道这一点,解决方案就非常简单。

调用之后

- presentViewController:animated:completion: 

过渡协调员已经被框架正确配置。

使用

- animateAlongsideTransition:completion: 

在此发送正确的完成块。

这是一个小代码片段,更好地解释了解决方案。

void(^completion)() = ^() {
    [modalViewController dismissViewControllerAnimated:YES completion:nil];
};

// This check is needed if you need to support iOS version older than 7.0
BOOL canUseTransitionCoordinator = [viewController respondsToSelector:@selector(transitionCoordinator)];

if (animated && canUseTransitionCoordinator)
{
    [viewController presentViewController:modalViewController animated:animated completion:nil];
    [viewController.transitionCoordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        completion();
    }];
}
else
{
    [viewController presentViewController:modalViewController animated:animated completion:completion];
}

1

我的解决方案:

dismissViewControllerAnimated:completion:如果您连续呈现多个视图控制器,从而构建一个呈现的视图控制器堆栈,在堆栈较低的视图控制器上调用此方法将关闭其直接子视图控制器和该子视图控制器上方的所有视图控制器。当发生这种情况时,只有最顶层的视图以动画方式消失;任何中间的视图控制器都将从堆栈中简单地移除。

例如,我有四个视图:A->B->C->D,当我想要关闭B时,首先使用objc_setAssociatedObject附加/分离NSString对象来检查C是否也要关闭,如果C也想要关闭,则仅取消C的请求。只需调用B的dismiss即可。


-2
ThirdViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"Third"];
UIViewController *VC1 = self.presentingViewController;
[self dismissViewControllerAnimated:NO completion:^{}];
[VC1 presentViewController:vc animated:YES completion:^{}];

你能否在你的回答周围加上一些色彩?这样不会对任何人有所帮助。 - Mika
抱歉,我没明白你的意思。@Mika - Jr.Mob Application Developer
你刚刚放了几行代码。能否详细说明一下这些代码的作用以及为什么它是一个解决方案? - Mika
它执行与问题中的代码相同的操作。它会关闭当前视图控制器并呈现新的视图控制器,但它已经解决了正在转换的问题。 - Jr.Mob Application Developer

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