Я использую интерактивный пользовательский переход с помощью UIPercentDrivenInteractiveTransition. Устройство распознавания жестов успешно вызывает контроллер взаимодействия updateInteractiveTransition. Аналогично, анимация успешно завершается, когда я вызываю контроллер взаимодействия finishInteractiveTransition.
Но иногда я получаю дополнительный бит отвлекающей анимации в конце (где, похоже, повторяется вторая часть анимации). При достаточно простых анимациях я редко вижу этот симптом на iPhone 5 (хотя я регулярно вижу его на симуляторе при работе на медленном ноутбуке). Если сделать анимацию более дорогостоящей (т.е. Много теней, нескольких видов, анимационных разных направлениях и т.д.), Частота этой проблемы на устройстве увеличивается.
Кто-нибудь еще видел эту проблему и выяснил решение, отличное от оптимизации анимаций (что я, по общему признанию, должен делать в любом случае) и/или написания своих собственных контроллеров взаимодействия? Подход UIPercentDrivenInteractiveTransition имеет определенную элегантность, но мне неловко с тем, что он неверно ведет себя недетерминированно. Кто-нибудь видел это поведение? Кто-нибудь знает о других решениях?
Чтобы проиллюстрировать эффект, см. изображение ниже. Обратите внимание, что вторая сцена, красная точка, когда заканчивается анимация, повторяет вторую часть своей анимации второй раз.

Эта анимация генерируется:
-
повторно вызывающий
updateInteractiveTransition, прогрессирующее обновление от 0% до 40%; -
кратковременно приостанавливается (поэтому вы можете различать интерактивный переход и анимацию завершения в результате
finishInteractiveTransition); -
затем вызов
finishInteractiveTransitionдля завершения анимации; и -
анимация контроллера анимации
completionблокирует вызовыcompleteTransitionдляtransitionContext, чтобы очистить все.
Выполняя некоторые диагностические операции, похоже, что именно этот последний шаг вызывает этот посторонний бит анимации. Блок завершения контроллера анимации вызывается, когда анимация завершена, но как только я вызываю completeTransition, он иногда повторяет последний бит анимации (особенно при использовании сложных анимаций).
Я не считаю это актуальным, но это мой код для настройки контроллера навигации для выполнения интерактивных переходов:
- (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 (даже если анимация действительно была выполнена в этой точке). Это предполагает, что эта дополнительная анимация могла быть результатом вызова completeTransition.
FYI, я сделал этот эксперимент с распознающим жестом:
- (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];
}
}
}
Я также сделал это, вызвав updateInteractiveTransition и finishInteractiveTransition вручную (исключая распознаватель жестов из уравнения), и он по-прежнему демонстрирует это странное поведение:
[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 сложными анимациями. Я могу свести к минимуму проблему, упростив их (например, снимки моментальных снимков и анимированные снимки). Я также подозреваю, что могу решить эту проблему, не используя UIPercentDrivenInteractiveTransition и записывая свой собственный контроллер взаимодействия, который бы сам выполнял анимацию, не пытаясь интерполировать блок animationWithDuration.
Но мне было интересно, придумали ли какие-либо другие трюки использовать UIPercentDrivenInteractiveTransition со сложными анимациями.