Oprócz odpowiedzi Brada Larsona : dla warstw niestandardowych (które są tworzone przez Ciebie) możesz użyć delegowania zamiast modyfikowania actions
słownika warstwy . To podejście jest bardziej dynamiczne i może być bardziej wydajne. I umożliwia wyłączenie wszystkich niejawnych animacji bez konieczności wyszczególniania wszystkich animowanych klawiszy.
Niestety, nie można używać UIView
s jako delegatów warstwy niestandardowej, ponieważ każda z nich UIView
jest już delegatem swojej własnej warstwy. Ale możesz użyć prostej klasy pomocniczej, takiej jak ta:
@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
Zastosowanie (wewnątrz widoku):
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
Czasami wygodnie jest mieć kontroler widoku jako delegata dla niestandardowych podwarstw widoku; w tym przypadku nie ma potrzeby stosowania klasy pomocniczej, można zaimplementować actionForLayer:forKey:
metodę bezpośrednio w kontrolerze.
Ważna uwaga: nie próbuj modyfikować delegata UIView
warstwy bazowej (np. Aby włączyć niejawne animacje) - zdarzają się złe rzeczy :)
Uwaga: jeśli chcesz animować (nie wyłączać animacji) przerysowania warstw, nie ma sensu umieszczać [CALayer setNeedsDisplayInRect:]
wywołania wewnątrz a CATransaction
, ponieważ faktyczne przerysowanie może (i prawdopodobnie nastąpi) później. Dobrym podejściem jest użycie właściwości niestandardowych, jak opisano w tej odpowiedzi .
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });