UIPercentDrivenInteractiveTransition在完成时产生无关的animation

我正在使用UIPercentDrivenInteractiveTransition进行交互式自定义推送转换。 手势识别器成功地调用交互控制器的updateInteractiveTransition 。 同样,当我调用交互控制器的finishInteractiveTransition时,animation成功完成。

但是,有时我会在最后看到额外的分散注意力的animation(似乎重复animation的后半部分)。 使用相当简单的animation,我很less在iPhone 5上看到这种症状(虽然我经常在慢速笔记本电脑上模拟器上看到它)。 如果我使animation在计算上更昂贵(例如,大量的阴影,animation不同方向的多个视图等),则设备上的这个问题的频率增加。

有没有其他人看到这个问题,并想出了一个解决scheme,而不是简化animation(我承认应该这样做)和/或编写我自己的交互控制器? UIPercentDrivenInteractiveTransition方法具有一定的优雅性,但是我对其不确定地行为不端的事实感到不安。 有其他人看到这种行为? 有谁知道其他解决scheme?

为了说明效果,请参阅下面的图片。 注意第二个场景,红色视图,当animation结束时,似乎是第二次重复animation的后半部分。

动画不正确

这个animation是由以下产生的:

  • 反复调用updateInteractiveTransition ,进度从0%更新到40%;

  • 暂时暂停(这样就可以区分交互式转换和由finishInteractiveTransition产生的完成animation);

  • 然后调用finishInteractiveTransition完成animation; 和

  • animation控制器的animationcompletion块为transitionContext调用completeTransition ,以清理所有东西。

做了一些诊断,似乎是触发这一无关animation的最后一步。 animation完成时调用animation控制器的完成块,但只要我调用completeTransition ,它有时会重复animation的最后一位(特别是在使用复杂animation时)。


我不认为这是相关的,但这是我的代码configuration导航控制器执行交互式转换:

 - (void)viewDidLoad { [super viewDidLoad]; self.navigationController.delegate = self; self.interationController = [[UIPercentDrivenInteractiveTransition alloc] init]; } - (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController*)fromVC toViewController:(UIViewController*)toVC { if (operation == UINavigationControllerOperationPush) return [[PushAnimator alloc] init]; return nil; } - (id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController*)navigationController interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>)animationController { return self.interationController; } 

我的PushAnimator是:

 @implementation PushAnimator - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext { return 5.0; } - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext { UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; [[transitionContext containerView] addSubview:toViewController.view]; toViewController.view.frame = CGRectOffset(fromViewController.view.frame, fromViewController.view.frame.size.width, 0);; [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{ toViewController.view.frame = fromViewController.view.frame; } completion:^(BOOL finished) { [transitionContext completeTransition:![transitionContext transitionWasCancelled]]; }]; } @end 

请注意,当我将日志声明放在我称之为completeTransition ,我可以看到,在我调用completeTransition (即使animation真的在那一刻完成)之后,会出现这种无关的animation。 这表明多余的animation可能是由completeTransition的调用引起的。

仅供参考,我已经用手势识别器完成了这个实验:

 - (void)handlePan:(UIScreenEdgePanGestureRecognizer *)gesture { CGFloat width = gesture.view.frame.size.width; if (gesture.state == UIGestureRecognizerStateBegan) { [self performSegueWithIdentifier:@"pushToSecond" sender:self]; } else if (gesture.state == UIGestureRecognizerStateChanged) { CGPoint translation = [gesture translationInView:gesture.view]; [self.interactionController updateInteractiveTransition:ABS(translation.x / width)]; } else if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateCancelled) { CGPoint translation = [gesture translationInView:gesture.view]; CGPoint velocity = [gesture velocityInView:gesture.view]; CGFloat percent = ABS(translation.x + velocity.x * 0.25 / width); if (percent < 0.5 || gesture.state == UIGestureRecognizerStateCancelled) { [self.interactionController cancelInteractiveTransition]; } else { [self.interactionController finishInteractiveTransition]; } } } 

我也是通过手动调用updateInteractiveTransitionfinishInteractiveTransition (消除方程中的手势识别器)来实现的,它仍然performance出这种奇怪的行为:

 [self performSegueWithIdentifier:@"pushToSecond" sender:self]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self.interactionController updateInteractiveTransition:0.40]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self.interactionController finishInteractiveTransition]; }); }); 

底线,我断定这是一个问题与UIPercentDrivenInteractiveTransition与复杂的animation分离。 我可以通过简化问题来最小化问题(例如快照和animation快照视图)。 我也怀疑我可以通过不使用UIPercentDrivenInteractiveTransition和编写我自己的交互控制器来解决这个问题,而这个交互控制器可以完成animation本身,而不需要插入animationWithDuration块。

但是我想知道是否有人想出了使用UIPercentDrivenInteractiveTransition和其他复杂animation的技巧。

我见过类似的东西。 我有两种可能的解决方法。 一种是在animation完成处理程序中使用延迟的性能:

 } completion:^(BOOL finished) { double delayInSeconds = 0.1; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ BOOL cancelled = [transitionContext transitionWasCancelled]; [transitionContext completeTransition:!cancelled]; }); self.interacting = NO; }]; 

另一种可能性是:不要使用百分比驱动器animation! 当手动驾驶交互式自定义animation时,我从来没有像这样的问题。

这个问题只在模拟器中出现。

解决scheme:self.interactiveAnimator.completionSpeed = 0.999;

错误报告在这里: http : //openradar.appspot.com/14675246

在我的情况下这个错误的原因是多次设置视图的框架。 我只是设置视图框架一次,它解决了我的问题。

所以在这种情况下,“toViewController.view”的框架被设置为TWICE,从而使animation具有不需要的行为