В дополнение к ответ Брэда Ларсона : для пользовательских слоев (которые вы создали) вы можете использовать делегирование вместо изменения словаря 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
, потому что реальное перерисовывание может (и, вероятно, произойдет) иногда позже. Хорошим подходом является использование пользовательских свойств, как описано в этом ответе .