Окрім відповіді Бреда Ларсона : для користувацьких шарів (які створені вами) ви можете використовувати делегування замість actions
словника словника. Цей підхід є більш динамічним і може бути більш ефективним. І це дозволяє відключити всі неявні анімації без перерахування всіх анімаційних ключів.
На жаль, неможливо використовувати UIView
s як власні делегати шару, оскільки кожен UIView
це вже делегат власного шару. Але ви можете використовувати простий клас помічників на кшталт цього:
@interface MyLayerDelegate : NSObject
@property (nonatomic, assign) BOOL disableImplicitAnimations;
@end
@implementation MyLayerDelegate
- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event
{
if (self.disableImplicitAnimations)
return (id)[NSNull null]; // disable all implicit animations
else return nil; // allow implicit animations
// you can also test specific key names; for example, to disable bounds animation:
// if ([event isEqualToString:@"bounds"]) return (id)[NSNull null];
}
@end
Використання (всередині подання):
MyLayerDelegate *delegate = [[MyLayerDelegate alloc] init];
// assign to a strong property, because CALayer's "delegate" property is weak
self.myLayerDelegate = delegate;
self.myLayer = [CALayer layer];
self.myLayer.delegate = delegate;
// ...
self.myLayerDelegate.disableImplicitAnimations = YES;
self.myLayer.position = (CGPoint){.x = 10, .y = 42}; // will not animate
// ...
self.myLayerDelegate.disableImplicitAnimations = NO;
self.myLayer.position = (CGPoint){.x = 0, .y = 0}; // will animate
Іноді зручно мати контролер виду в якості делегата для користувацьких підшарів перегляду; в цьому випадку немає необхідності в класі помічників, ви можете реалізувати actionForLayer:forKey:
метод прямо всередині контролера.
Важлива примітка: не намагайтеся змінювати делегат UIView
базового шару (наприклад, щоб включити неявну анімацію) - погані речі відбудуться :)
Примітка. Якщо ви хочете анімувати (не відключати анімацію для) шару, перемальовується, марно ставити [CALayer setNeedsDisplayInRect:]
виклик всередині а CATransaction
, оскільки фактичне перемальовування може (і, ймовірно, буде) траплятися іноді пізніше. Хороший підхід - використовувати власні властивості, як описано в цій відповіді .
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });