Подтвердить что ты не робот

Ошибка анимации iOS 8

У меня есть простой способ просмотра анимации.

-(void)animateSelf
{
    CABasicAnimation * animation;

    animation = [CABasicAnimation animationWithKeyPath:@"position.y"];
    // settings ...
    [self.view.layer addAnimation:animation forKey:@"position.y"];

    animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    // settings ...
    [self.view.layer addAnimation:animation forKey:@"transform.rotation.z"];

    [UIView animateWithDuration: 1.0 animations:^{
        CGRect rect = self.view.frame;
        rect.origin.y += 800;
        self.view.frame = rect;
    } completion:nil];
}

Для iOS 7 он работал хорошо. Но для iOS 8 анимация ведет себя непредсказуемо. Есть ли способ объединить эти анимации для iOS 8?

Я попытался заменить animateWithDuration: другим CABasicAnimation, но это не помогло. Журналы view.frame верны, но анимация view.frame выпрыгивает из неясного происхождения.

После удаления CABasicAnimation для position.y (первого) ошибка исчезла.

4b9b3361

Ответ 1

У вас есть три анимации:

  • Вы анималируете слой position
  • Вы анималируете слой transform
  • Вы анимируете представление frame, которое, в свою очередь, анимирует слой position.

Анимации 1 и 3 сталкиваются.

  • В iOS 7 поведение заключается в том, что анимация 3 отменяет анимацию 1.
  • В iOS 8 поведение заключается в том, что анимации 1 и 3 выполняются одновременно ( "Additive Animations" ).

Я предлагаю вам просто удалить анимацию 1, а также проверить связанный видеоролик WWDC 2014 (я думаю, что это было Building Interruptible and Responsive Interactions).

Ответ 2

Что сработало для меня, так это отключить автозапуск в представлении и SUBVIEWS представления, которое я анимационировал в какой-то момент перед анимацией. Отключение автоспуска из раскадровки было недостаточно в iOS8.

[viewToAnimate removeFromSuperview];
[viewToAnimate setTranslatesAutoresizingMaskIntoConstraints:YES];
//addSubview again at original index
[superView insertSubview:viewToAnimate atIndex:index];

Ответ 3

Этот пример может помочь вам, мне жаль, что я не обнаружил его, прежде чем тратить часы. Вместо анимации frame анимируется его contraints. Нажмите на ограничение автоматического макета, которое вы хотите настроить (в построителе интерфейса, например, в верхнем ограничении). Затем сделайте это IBOutlet;

@property (strong, nonatomic) IBOutlet NSLayoutConstraint *topConstraint;

Анимация вверх;

self.topConstraint.constant = -100;    
[self.viewToAnimate setNeedsUpdateConstraints]; 
[UIView animateWithDuration:1.5 animations:^{
    [self.viewToAnimate layoutIfNeeded]; 
}];

Анимация назад в исходное место

self.topConstraint.constant = 0;    
[self.viewToAnimate setNeedsUpdateConstraints];  
[UIView animateWithDuration:1.5 animations:^{
    [self.viewToAnimate layoutIfNeeded];
}];

Первоначально отправленный мной здесь

Итак, вы бы скорректировали ограничение для self.view.frame в вашем примере.

Ответ 4

У меня также возникла проблема с небольшими неприятными различиями между анимацией iOS7 и iOS8. В большинстве случаев это было сломано:

  • единственная комбинация масштабирования, преобразования и поворота CGAffineTransforms - результат зависел от версии iOS
  • или сложная последовательность анимаций на разных представлениях - некоторые представления "переписывали" свои позиции перед началом нового фрагмента анимации. Было затронуто около 5% фрагментов анимации.

Я уверен, что одновременных анимаций в проблемных представлениях не было. Предложения Autolayout и ограничений не помогли (более того, все анимированные представления были созданы в коде, поскольку автоматическое отключение сильно искажало анимацию даже до iOS8).

То, что оказалось универсальным решением для обеих задач, состоит в том, чтобы помещать проблематичные представления в представление оболочки и использовать его для разделения анимации вращения или сделать анимацию, которая вызывает эффект "reset". Теперь он функционирует одинаково в 7.1.1 и 8.1.1.