На днях потребовалось написать класс, который бы умел выполнять анимации в сериальном порядке, которые мы бы передавали в массиве. Так же требовалось, чтобы по окончанию всех анимаций был общий callback блок. Хотелось бы поделиться с вами получившимся результатом.

Во-первых, какие свойства должен уметь класс, который выполняет анимации? Я обозначил для себя несколько свойств, которые определил в интерфейсе класса:

@property (nonatomic, assign) NSTimeInterval duration;
@property (nonatomic, assign) NSTimeInterval delay;

Собственно, я посчитал, что этих свойств вполне достаточно для работы класса.

Во-вторых, я обозначил два метода:

Метод инициализатор:

- (instancetype)initWithDuration:(NSTimeInterval)duration
                           delay:(NSTimeInterval)delay;

И метод, в который бы мы передавали массив с блоками анимаций и completionBlock:

- (void)doAnimations:(NSArray *)animations completion:(CompletionBlock)completion;

Перейдем к реализации класса!

С методом инициализации в принципе все довольно ожидаемо:

- (instancetype)initWithDuration:(NSTimeInterval)duration
                           delay:(NSTimeInterval)delay
{
    if (self = [super init]) {
        _duration = duration;
        _delay = delay;
    }
    return self;
}

И наконец, сам метод, который выполняет анимации:

- (void)doAnimations:(NSArray *)animations completion:(CompletionBlock)completion
{
//Перебираем массив с блоками анимаций. Используем метод addKeyframeWithRelativeStartTime, для того, чтобы анимации выполнялись в нужном нам порядке по времени.
    AnimationBlock animationsBlock = ^{
        [animations enumerateObjectsUsingBlock:^(AnimationBlock animation, NSUInteger index, BOOL *stop) {
            [UIView addKeyframeWithRelativeStartTime:index/(CGFloat)animations.count
                                    relativeDuration:1/(CGFloat)animations.count
                                          animations:animation];
        }];
    };
//В конце передаем блок с нашими анимациями в метод animateKeyframesWithDuration, где duration мы рассчитываем как длительность анимации умноженное на количество переданных анимаций. И в итоге получаем конечный callback блок.    
    [UIView animateKeyframesWithDuration:self.duration * animations.count
                                   delay:self.delay
                                 options:UIViewKeyframeAnimationOptionCalculationModeLinear | UIViewAnimationOptionCurveLinear
                              animations:animationsBlock
                              completion:completion];
}

Небольшая цитата одного из источников данного решения:

“UIView key-frame animations require the use of 2 methods, the first of which is similar to the other block-based animation methods:

animateKeyframesWithDuration:delay:options:animations:completion: 

This takes floats for duration and delay, a bit-mask for options and blocks for animation and completion - all pretty standard in the world of UIView animations. The difference comes in the method we call inside the animation block:

addKeyframeWithRelativeStartTime:relativeDuration:animations:

This method is used to add the fixed points within the animation sequence.”

На этом все! Возможно есть еще варианты решения данной задачи, но долгими поисками, я для себя нашел именно такое. Всем спасибо за внимание!