En plus de la réponse de Brad Larson : pour les couches personnalisées (que vous avez créées), vous pouvez utiliser la délégation au lieu de modifier le actions
dictionnaire des couches . Cette approche est plus dynamique et peut être plus performante. Et il permet de désactiver toutes les animations implicites sans avoir à lister toutes les clés animables.
Malheureusement, il est impossible d'utiliser les UIView
s comme délégués de couche personnalisés, car chacun UIView
est déjà un délégué de sa propre couche. Mais vous pouvez utiliser une classe d'assistance simple comme celle-ci:
@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
Utilisation (à l'intérieur de la vue):
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
Parfois, il est pratique d'avoir le contrôleur de vue comme délégué pour les sous-couches personnalisées de vue; dans ce cas, il n'y a pas besoin d'une classe d'assistance, vous pouvez implémenter la actionForLayer:forKey:
méthode directement dans le contrôleur.
Note importante: n'essayez pas de modifier le délégué de UIView
la couche sous-jacente (par exemple pour activer des animations implicites) - de mauvaises choses vont arriver :)
Remarque: si vous souhaitez animer (et non désactiver l'animation pour) les redessins de calques, il est inutile de mettre un [CALayer setNeedsDisplayInRect:]
appel à l'intérieur de a CATransaction
, car un redessinage réel peut (et se produira probablement) parfois plus tard. La bonne approche consiste à utiliser des propriétés personnalisées, comme décrit dans cette réponse .
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });