UIPercentDrivenInteractiveTransition无法在快速手势上完成动画

我创建了一个交互式过渡。 我的func animateTransition(transitionContext: UIViewControllerContextTransitioning)很正常,我得到容器UIView ,我添加了两个UIViewControllers然后我在UIView.animateWithDuration(duration, animations, completion)做动画更改。

我从UIViewController添加了一个UIScreenEdgePanGestureRecognizer 。 它运作良好,除非我做一个非常快速的平底锅。

在最后一个场景中,应用程序没有响应,仍然在相同的UIViewController (转换似乎没有工作)但后台任务运行。 当我运行Debug View Hierarchy ,我看到新的UIViewController而不是前一个,而前一个(至少它的UIView )代表它应该在转换结束时站立的位置。

我做了一些打印和检查点,从中我可以说,当问题发生时, 动画的完成 (我的animateTransition方法中的那个) 没有到达 ,所以我不能调用transitionContext.completeTransition方法来完成或不转换。

我也可以看到泛有时从UIGestureRecognizerState.Began直接进入UIGestureRecognizerState.Ended而不经过UIGestureRecognizerState.Changed

当它通过UIGestureRecognizerState.Changed ,每个UIGestureRecognizerState.Changed状态的translation velocity保持不变。

编辑:

这是代码:

animateTransition方法

 func animateTransition(transitionContext: UIViewControllerContextTransitioning) { self.transitionContext = transitionContext let containerView = transitionContext.containerView() let screens: (from: UIViewController, to: UIViewController) = (transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!, transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!) let parentViewController = presenting ? screens.from : screens.to let childViewController = presenting ? screens.to : screens.from let parentView = parentViewController.view let childView = childViewController.view // positionning the "to" viewController's view for the animation if presenting { offStageChildViewController(childView) } containerView.addSubview(parentView) containerView.addSubview(childView) let duration = transitionDuration(transitionContext) UIView.animateWithDuration(duration, animations: { if self.presenting { self.onStageViewController(childView) self.offStageParentViewController(parentView) } else { self.onStageViewController(parentView) self.offStageChildViewController(childView) }}, completion: { finished in if transitionContext.transitionWasCancelled() { transitionContext.completeTransition(false) } else { transitionContext.completeTransition(true) } }) } 

手势和手势处理程序:

 weak var fromViewController: UIViewController! { didSet { let screenEdgePanRecognizer = UIScreenEdgePanGestureRecognizer(target: self, action: "presentingViewController:") screenEdgePanRecognizer.edges = edge fromViewController.view.addGestureRecognizer(screenEdgePanRecognizer) } } func presentingViewController(pan: UIPanGestureRecognizer) { let percentage = getPercentage(pan) switch pan.state { case UIGestureRecognizerState.Began: interactive = true presentViewController(pan) case UIGestureRecognizerState.Changed: updateInteractiveTransition(percentage) case UIGestureRecognizerState.Ended: interactive = false if finishPresenting(pan, percentage: percentage) { finishInteractiveTransition() } else { cancelInteractiveTransition() } default: break } } 

知道会发生什么吗?

编辑2:

以下是未公开的方法:

 override func getPercentage(pan: UIPanGestureRecognizer) -> CGFloat { let translation = pan.translationInView(pan.view!) return abs(translation.x / pan.view!.bounds.width) } override func onStageViewController(view: UIView) { view.transform = CGAffineTransformIdentity } override func offStageParentViewController(view: UIView) { view.transform = CGAffineTransformMakeTranslation(-view.bounds.width / 2, 0) } override func offStageChildViewController(view: UIView) { view.transform = CGAffineTransformMakeTranslation(view.bounds.width, 0) } override func presentViewController(pan: UIPanGestureRecognizer) { let location = pan.locationInView((fromViewController as! MainViewController).tableView) let indexPath = (fromViewController as! MainViewController).tableView.indexPathForRowAtPoint(location) if indexPath == nil { pan.state = .Failed return } fromViewController.performSegueWithIdentifier("chartSegue", sender: pan) } 
  • 我删除了“over”添加行=>没有修复它
  • 我在.Ended添加了updateInteractiveTransition ,在.Ended ,在=>中都没有修复它
  • 我在我的toViewController的视图层打开了toViewController并且一直让它开始=>没有修复它

但问题是,在进行快速交互式手势时,为什么它的响应速度不够快

只要我的手指足够长,它实际上可以使用快速交互式手势。 例如,如果我在超过(比方说)1cm时非常快速地平移,那就没关系。 如果我在小于1厘米的小表面(再说一次)上快速平移,那就不行了

可能的候选者包括动画的视图太复杂(或具有阴影等复杂效果)

我也考虑过复杂的观点,但我认为我的观点并不复杂。 有一堆按钮和标签,一个自定义UIControl充当分段,一个图表(一旦控制器出现就加载),并在viewController中加载一个xib。


好的,我刚刚创建了一个包含MINIMUM类和对象的项目 ,以便触发问题。 因此,要触发它,您只需从右向左快速轻扫即可。

我注意到它第一次很容易工作,但如果你第一次正常拖动视图控制器,那么触发它会更加困难(甚至不可能?)。 在我的完整项目中,它并不重要。

当我诊断出这个问题时,我注意到在animateTransition运行之前,手势的变化和结束的状态事件正在发生。 所以动画在它开始之前就被取消/完成了!

我尝试使用GCD动画同步队列,以确保UIPercentDrivenInterativeTransition的更新直到`animate:之后才会发生:

 private let animationSynchronizationQueue = dispatch_queue_create("com.domain.app.animationsynchronization", DISPATCH_QUEUE_SERIAL) 

然后我有一个实用工具方法来使用这个队列:

 func dispatchToMainFromSynchronizationQueue(block: dispatch_block_t) { dispatch_async(animationSynchronizationQueue) { dispatch_sync(dispatch_get_main_queue(), block) } } 

然后我的手势处理程序确保更改和结束状态通过该队列路由:

 func handlePan(gesture: UIPanGestureRecognizer) { switch gesture.state { case .Began: dispatch_suspend(animationSynchronizationQueue) fromViewController.performSegueWithIdentifier("segueID", sender: gesture) case .Changed: dispatchToMainFromSynchronizationQueue() { self.updateInteractiveTransition(percentage) } case .Ended: dispatchToMainFromSynchronizationQueue() { if isOkToFinish { self.finishInteractiveTransition() } else { self.cancelInteractiveTransition() } } default: break } } 

所以,我有手势识别器的.Began状态暂停该队列,我让动画控制器在animationTransition恢复该队列(确保队列在该方法运行之后再次启动,然后手势继续尝试更新UIPercentDrivenInteractiveTransition对象。