除了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
's 底层的委托(例如启用隐式动画)- 会发生不好的事情 :)
注意:如果你想动画(不禁用动画)图层重绘,将[CALayer setNeedsDisplayInRect:]
call 放在 a 内是没有用的CATransaction
,因为实际重绘可能(并且可能会)有时会发生。好的方法是使用自定义属性,如本答案中所述。