Я только что нашел еще лучший способ сделать код завершения для CAAnimations:
Я создал typedef для блока:
typedef void (^animationCompletionBlock)(void);
И ключ, который я использую, чтобы добавить блок к анимации:
#define kAnimationCompletionBlock @"animationCompletionBlock"
Затем, если я хочу запустить код завершения анимации после завершения CAAnimation, я устанавливаю себя в качестве делегата анимации и добавляю блок кода в анимацию, используя setValue: forKey:
animationCompletionBlock theBlock = ^void(void)
{
//Code to execute after the animation completes goes here
};
[theAnimation setValue: theBlock forKey: kAnimationCompletionBlock];
Затем я реализую метод animationDidStop: finish:, который проверяет наличие блока по указанному ключу и выполняет его, если он найден:
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
animationCompletionBlock theBlock = [theAnimation valueForKey: kAnimationCompletionBlock];
if (theBlock)
theBlock();
}
Прелесть этого подхода в том, что вы можете написать код очистки в том же месте, где вы создаете объект анимации. Более того, поскольку код является блоком, он имеет доступ к локальным переменным в той области видимости, в которой он определен. Вам не нужно возиться с настройкой словарей userInfo или другой подобной ерундой, и вам не нужно писать постоянно растущий метод animationDidStop: finish:, который становится все более сложным по мере добавления различных видов анимации.
По правде говоря, CAAnimation должна иметь встроенное свойство блока завершения и поддержку системой для его автоматического вызова, если он указан. Однако приведенный выше код предоставляет вам ту же функциональность с помощью всего лишь нескольких строк дополнительного кода.