Xcode 10:自定义动画过渡卡住

Xcode 10: Custom Animated Transitions Stuck

我的应用程序有两个视图控制器(VC A 和 B)和它们之间的自定义转换。

在 VC A 上使用向左平移手势时,交互式动画过渡以模态方式呈现 VC B 在 A 上从右侧(从右到左)滑入。 要关闭 VC B,用户可以:

问题是在 Xcode 10 Seed(构建 10A254a)+ iOS 12 模拟器(X 或 XR 或 XS)上进行测试 自定义转换永远不会完成并且 UI 处于一种奇怪的状态 :

此问题从未出现在 Xcode and/or iOS pre Xcode 10/iOS12.

之前的任何版本中

这是我自定义的 animateTransition 方法 UIViewControllerAnimatedTransitioning

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

    guard let fromVC = transitionContext.viewController(forKey: .from), let toVC = transitionContext.viewController(forKey: .to) else {
        transitionContext.completeTransition(false)
        return
    }

    let containterView = transitionContext.containerView
    containterView.insertSubview(toVC.view, belowSubview: fromVC.view)

    let bounds = fromVC.view.bounds
    var xOffsetMultiplier : CGFloat = 0.0
    var yOffsetMultiplier : CGFloat = 0.0

    switch direction {
    case .up:
        yOffsetMultiplier  = -1.0
    case .right:
        xOffsetMultiplier  = 1.0
    case .left:
        xOffsetMultiplier  = -1.0
    case .down:
        yOffsetMultiplier  = 1.0
    }

    print(xOffsetMultiplier,bounds.size.width,bounds.size.height )
    UIView.animate(withDuration: duration, animations: {
        print("animating...")
        //fromVC.navigationController?.navigationBar.alpha = 0.0
        fromVC.view.frame = fromVC.view.frame.offsetBy(dx: xOffsetMultiplier * bounds.size.width, dy: yOffsetMultiplier * bounds.size.height)
    }, completion: { finished in
        print("completed animation")
        transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        //fromVC.navigationController?.navigationBar.alpha = 1.0
    })

}

那里的印刷品只是为了调试。

这是很容易重现问题的序列:

  1. 使用平移手势启动从 B 回到 A 的交互式过渡,但永远不会完成它 - 这将在 UIPercentDrivenInteractiveTransition 对象上调用 cancel() + 我可以验证动画是否已完成。
  2. 点击 'close' 按钮调用非交互式过渡以关闭 B。B 永远不会关闭,自定义动画永远不会完成!

在设备上我根本无法重现此问题(目前)- 所有转换都按预期工作。

所以找到了为什么转换卡在 VC B 和 A 之间的原因,但仍然不真正理解 Xcode9/iOS11 和 Xcode10/iOS12 之间产生不同行为的区别。

为了简短起见:

  • 当使用平移手势启动交互式转换以关闭 VC B 时,我分配了一个 UIPercentDrivenInteractiveTransition,在 VC 上调用 dismiss(animated:completion:) 并根据泛进步。在某些情况下,当平移没有足够遍历时 "ground" 我的手势处理程序认为转换已取消并调用 UIPercentDrivenInteractiveTransition
  • cancel() 方法
  • 在这样的取消之后,点击关闭按钮会启动一个新的 dismiss(animated:completion:) 但是因为 UIPercentDrivenInteractiveTransition 仍然被分配,它被我的转换委托返回并且 OS 实际上尝试了一个交互式解雇,尽管这不是本意。这是我的一个错误,因为在调用 cancel 之后我还应该确保在这种情况下转换委托不会尝试交互式转换(尽管在 Xcode9/iOS11 上它没有)。
  • 过渡是 'stuck' 的原因是因为它是一个没有更新的交互式过渡(点击 [=40= 时没有手势更新)。我通过错误地强制执行 finish() 来验证这一点分配 UIPercentDrivenInteractiveTransition 所以它完成,一切都恢复正常。

根据用户交互确保关闭过渡是交互的或非交互的,尤其是在取消交互之后,解决了这个问题。

我不明白的是为什么 Xcode/iOS 版本之间的行为不一致。这个问题以前从未在任何设备或模拟器上发生过。 自定义 animations/transitions 的处理方式有所不同 - Apple 文档中没有任何内容可以解释这一点 - 可能在过渡上下文的内部实现中。

从天真的"eye-test"看来,Xcode10模拟器上的过渡动画反应时间较慢,而且不如以前流畅,但仍然没有完全解释它。

尝试在您的 UIPercentDrivenInteractiveTransition

中设置 wantsInteractiveStart = false