В дополнение к ответу Брэда Ларсона : для настраиваемых слоев (которые созданы вами) вы можете использовать делегирование вместо изменения 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];
else return nil;
}
@end
Использование (внутри представления):
MyLayerDelegate *delegate = [[MyLayerDelegate alloc] init];
self.myLayerDelegate = delegate;
self.myLayer = [CALayer layer];
self.myLayer.delegate = delegate;
self.myLayerDelegate.disableImplicitAnimations = YES;
self.myLayer.position = (CGPoint){.x = 10, .y = 42};
self.myLayerDelegate.disableImplicitAnimations = NO;
self.myLayer.position = (CGPoint){.x = 0, .y = 0};
Иногда удобно иметь контроллер представления в качестве делегата для настраиваемых подслоев представления; в этом случае нет необходимости во вспомогательном классе, вы можете реализовать actionForLayer:forKey:
метод прямо внутри контроллера.
Важное примечание: не пытайтесь изменить делегат UIView
нижележащего слоя (например, для включения неявной анимации) - будут плохие вещи :)
Примечание: если вы хотите анимировать (а не отключать анимацию для) перерисовки слоя, бесполезно помещать [CALayer setNeedsDisplayInRect:]
вызов внутри a CATransaction
, потому что фактическая перерисовка может (и, вероятно, будет) иногда происходить позже. Хороший подход - использовать настраиваемые свойства, как описано в этом ответе .
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });