Как вы анимируете подслои слоя UIView во время анимации UIView?

В анимации UIView для представления вы можете анимировать свои подпрограммы, которые выкладываются, включая UIViewAnimationOptionLayoutSubviews в параметре параметров [UIView animateWithDuration:delay:options:animations:completion:]. Тем не менее, я не могу найти способ анимировать его, выкладывая его подслои, когда они не являются некоторым слоем поддержки; они просто встанут на место, чтобы соответствовать новым границам вида. Поскольку я работаю со слоями, а не с представлениями, мне кажется, что я должен использовать Core Animation вместо анимации UIView, но я не знаю, как (и когда) делать это так, чтобы анимация слоя соответствовала представлению анимации.

Что мой основной вопрос. Подробнее, если вы хотите узнать конкретную вещь, которую я пытаюсь выполнить.

Я создал представление с пунктирной рамкой, добавив CAShapeLayer к слою представления (см. этот вопрос в стеке: Пунктирная граница линии вокруг UIView). Я настраиваю путь CAShapeLayer для соответствия границам вида в layoutSubviews.

Это работает, но есть одна косметическая проблема: когда границы представлений анимируются в анимации UIView (например, во время ротации), пунктирная граница переходит к новым границам представления, а не плавно анимирует ее, поскольку анимация вида его границ. То есть, правая и нижняя части пунктирной границы не будут соответственно оставаться в правой и нижней частях представления по мере оживления представления. Как я могу получить пунктирную границу от CAShapeLayer для анимации рядом с представлением, поскольку он оживляет его границы?

То, что я делаю до сих пор, это привязка CABasicAnimation к CAShapeLayer:

- (void)layoutSubviews
{
    [super layoutSubviews];

    self.borderLayer.path = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
    self.borderLayer.frame = self.bounds;

    CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
    [self.borderLayer addAnimation:pathAnimation forKey:nil];
}

Это приводит к тому, что пунктирная граница будет анимирована, но она не имеет правильной функции синхронизации и продолжительности анимации для соответствия анимации вида. Кроме того, иногда мы не хотим, чтобы пунктирная граница была похожа на анимацию, например, когда представление сначала выполняет макет, граница не должна анимироваться с какого-то старого пути на новый правильный путь; он должен просто появиться.

Ответ 1

Возможно, вы уже нашли ответ, но недавно я столкнулся с аналогичными проблемами, так как решил его, я отправлю ответ.

В методе - layoutSubViews вы можете получить текущую анимацию UIView как фоновый слой CAAnimation с помощью метода - animationForKey:. Используя это, вы можете реализовать - layoutSubViews как:

- (void)layoutSubviews {
    [super layoutSubviews];

    // get current animation for bounds
    CAAnimation *anim = [self.layer animationForKey:@"bounds"];

    [CATransaction begin];
    if(anim) {
        // animating, apply same duration and timing function.
        [CATransaction setAnimationDuration:anim.duration];
        [CATransaction setAnimationTimingFunction:anim.timingFunction];

        CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
        [self.borderLayer addAnimation:pathAnimation forKey:@"path"];
    }
    else {
        // not animating, we should disable implicit animations.
        [CATransaction disableActions];
    }

    self.borderLayer.path = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
    self.borderLayer.frame = self.bounds;
    [CATransaction commit];
}