我的应用程序有两个视图控制器(VC A 和 B)以及它们之间的自定义转换。
在 VC A 上使用向左平移手势时,交互式动画过渡以模态方式呈现 VC B 在 A 上从右侧滑入(从右到左)。要解除 VC B,用户可以:
- 使用向右平移手势:将触发交互转换,将 VC B 滑回右侧并露出 VC A。VC B 的位置由平移手势状态交互确定。交互由
UIPercentDrivenInteractiveTransition
对象“驱动”。 - 使用 VC B 导航栏上的“关闭”按钮。这将触发自定义过渡(向右滑动),没有交互(只是动画)。
问题是在 Xcode 10 Seed (build 10A254a) + iOS 12 Simulator (X or XR or XS) 上进行测试我可以很容易地进入自定义转换永远不会完成并且 UI 处于奇怪状态的状态:
- UI 卡在 VC B 上,没有手势或点击工作。
- 该应用程序没有卡住 - 我可以看到控制台日志仍在滚动并且网络活动正在运行(日志中没有错误)
- 在这种卡住状态下暂停应用程序我可以看到 com.apple.main-thread 没有卡住。
- 当我点击“Debug View Hierarchy”时,发生了一些奇怪的事情:在模拟屏幕上我仍然可以看到VC B 并且所有 UI 都已禁用。在视图调试器主视图上 - 我可以看到绘制的 VC A 的子视图,就好像转换完成一样。在视图调试器左树视图上-我可以看到VC B 的视图层次结构。
此问题从未出现在任何先前版本的 Xcode 和/或 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
})
}
打印件仅用于调试。
这是很容易重现问题的序列:
- 使用平移手势开始从 B 到 A 的交互式过渡,但从不完成 - 这将调用
cancel()
对象UIPercentDrivenInteractiveTransition
+ 我可以验证动画是否完成。 - 点击“关闭”按钮以调用非交互式过渡来关闭 B。B 永远不会关闭,并且自定义动画永远不会完成!
在设备上,我(还)根本无法重现这个问题——所有转换都按预期工作。