How to disable implicit CALayer animations?

It drives me crazy! I am working on a graphical application. Say I'm working on a UIView table.

I add some sublayers to this view ( [sheet.layer addSublayer:...] ) and then I want to draw them. To do this, I create a CGImageRef and put it in the contents layer. But he perked up, and I don't want that.

I tried everything:

  • removeAnimationForKey:
  • removeAllAnimations
  • install action dictionary
  • using actionlayer delegate
  • [CATransaction setDisableAnimations:YES]

Seems right. I don’t understand why this layer is still animated; _;
Am I doing something wrong? Is there a secret way?

+36
ios animation calayer
Apr 29 2018-11-11T00:
source share
10 answers

You must explicitly disable the animation by wrapping your code in CATransaction

 [CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; layer.content = someImageRef; [CATransaction commit]; 
+37
May 01 '11 at 20:59
source share
β€” -

Swift

 CATransaction.begin() CATransaction.setDisableActions(true) // change layer properties that you don't want to animate CATransaction.commit() 
+28
Jan 22 '16 at 8:00
source share

Like Mac OS X 10.6 and iOS 3, CATransaction also has a setDisableActions method that sets the value for the kCATransactionDisableActions key.

 [CATransaction begin]; [CATransaction setDisableActions:YES]; layer.content = someImageRef; [CATransaction commit]; 

In Swift, I like to use this extension method:

 extension CATransaction { class func withDisabledActions<T>(_ body: () throws -> T) rethrows -> T { CATransaction.begin() CATransaction.setDisableActions(true) defer { CATransaction.commit() } return try body() } } 

Then you can use it as follows:

 CATransaction.withDisabledActions { // your stuff here } 
+15
Feb 22 '15 at 18:34
source share

Another way:

  • You must disable the default animation of your sheet layer, which is implicitly called adding a sublevel.

  • You should also use the content animation of each sublevel. Of course, you can use the "kCATransactionDisableActions" CATransaction every time you set sublayer.content. But you can turn off this animation once when you create a sublevel.




Here is the code:

 // disable animation of container sheet.layer.actions = [NSDictionary dictionaryWithObject:[NSNull null] forKey:@"sublayers"]; // disable animation of each sublayer sublayer.layer.actions = [NSDictionary dictionaryWithObject:[NSNull null] forKey:@"content"]; // maybe, you'll also have to disable "onOrderIn"-action of each sublayer. 
+11
Nov 03 '11 at 6:29
source share

Swift 2

I managed to turn off all animations as follows, where myView is the view you are working with:

 myView.layer.sublayers?.forEach { $0.removeAllAnimations() } 

And as a note, deleting all the layers:

 myView.layer.sublayers?.forEach { $0.removeFromSuperlayer() } 
+1
Oct 11 '16 at 15:12
source share

Reusable global code:

 /** * Disable Implicit animation * EXAMPLE: disableAnim{view.layer?.position = 20}//Default animation is now disabled */ func disableAnim(_ closure:()->Void){ CATransaction.begin() CATransaction.setDisableActions(true) closure() CATransaction.commit() } 

Add this code anywhere in your code (globally)

+1
Apr 22 '17 at 2:37 on
source share

Swift 4 extension:

 extension CATransaction { static func disableAnimations(_ completion: () -> Void) { CATransaction.begin() CATransaction.setDisableActions(true) completion() CATransaction.commit() } } 

Using:

  CATransaction.disableAnimations { // things you don't want to animate } 
+1
Feb 20 '19 at 10:24
source share

before adding a layer to your view using [self.layer addSublayer:yourCALayer] and also after it has already been added, you can disable certain animated properties of your CALayer by overwriting the animation key. The key that you set to NULL is named after the property, it shows how it is done for layer.position = CGPoint(x,y);

 yourCALayer.actions = [NSDictionary dictionaryWithObject:[NSNull null] forKey:@"position"]; 

Since the actions property is an NSDictionary that doesn’t allow nil to be stored, you set it explicitly for the NULL object using [NSNull null] , which is the same as (id)kCFNull You can do this for all sublevels by iterating over all sublevels of the viewing layer with. ..

 for (CALayer *iterationLayer in self.layer.sublayers ) { iterationLayer.actions = [NSDictionary dictionaryWithObject:[NSNull null] forKey:@"position"]; //or for multiple keys at once NSNull *nop = [NSNull null]; iterationLayer.actions = [NSDictionary dictionaryWithObjects:@[nop,nop] forKeys:@[@"position",@"contents"]]; } 
0
01 Oct '18 at 6:24
source share

This is an old question, but the problem remains. Sometimes you don’t need the animations that CALayer imposes on you. I was not happy with the transaction-based approach, as I just wanted to disable these actions. For the good. Here's a Swift 4 solution for a subclass of CALayer that lets you choose whether to allow an action or globally disable it. You can also subclass CAShapeLayer, CATextLayer with the same content:

 public class ActionCALayer: CALayer { public var allowActions: Bool = false override public func action(forKey event: String) -> CAAction? { return allowActions ? super.action(forKey: event) : nil } } 
0
Feb 12 '19 at 18:44
source share

I totally agree with Ryan. His answer is for MacOS, for iOS you add the following to create an NSNull () action. This question Disabling implicit animation in - [CALayer setNeedsDisplayInRect:] and the documentation in the header led me here

 // Disable the implicit animation for changes to position override open class func defaultAction(forKey event: String) -> CAAction? { if event == #keyPath(position) { return NSNull() } return super.defaultAction(forKey: event) } 
0
Jul 11 '19 at 0:51
source share



All Articles