Zusätzlich zu Brad Larsons Antwort : Für benutzerdefinierte Ebenen (die von Ihnen erstellt wurden) können Sie die Delegierung verwenden, anstatt die Ebenen zu ändernactions
Wörterbuch ändern. Dieser Ansatz ist dynamischer und kann performanter sein. Außerdem können alle impliziten Animationen deaktiviert werden, ohne dass alle animierbaren Schlüssel aufgelistet werden müssen.
Leider ist es nicht möglich, UIView
s als benutzerdefinierte Layer-Delegaten zu verwenden, da jeder UIView
bereits ein Delegat seiner eigenen Ebene ist. Sie können jedoch eine einfache Hilfsklasse wie diese verwenden:
@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
Verwendung (innerhalb der Ansicht):
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
Manchmal ist es praktisch, den Controller von view als Delegaten für die benutzerdefinierten Unterschichten von view zu haben. In diesem Fall ist keine Hilfsklasse erforderlich. Sie können die actionForLayer:forKey:
Methode direkt im Controller implementieren .
Wichtiger Hinweis: Versuchen Sie nicht, den Delegaten der UIView
zugrunde liegenden Ebene zu ändern (z. B. um implizite Animationen zu aktivieren) - es werden schlimme Dinge passieren :)
Hinweis: Wenn Sie Ebenen- Neuzeichnungen animieren (nicht deaktivieren) möchten, ist es sinnlos, einen [CALayer setNeedsDisplayInRect:]
Aufruf in eine zu setzen CATransaction
, da das tatsächliche Neuzeichnen manchmal (und wahrscheinlich auch später) erfolgen kann. Der gute Ansatz besteht darin, benutzerdefinierte Eigenschaften zu verwenden, wie in dieser Antwort beschrieben .
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });