除了Brad Larson的回答:对于自定义图层(由您创建),您可以使用委托而不是修改图层的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:]
调用放在a内是没有用的CATransaction
,因为实际的重绘可能(可能会)稍后发生。好的方法是使用自定义属性,如本答案所述。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });