How do you move a CALayer instantly (without animation)

IosObjective CCocoa TouchCore AnimationCalayer

Ios Problem Overview


I'm trying to drag a CALayer in an iOS app.

As soon as I change its position property it tries to animate to the new position and flickers all over the place:

 layer.position = CGPointMake(x, y)

How can I move CALayers instantly? I can't seem to get my head around the Core Animation API.

Ios Solutions


Solution 1 - Ios

You want to wrap your call in the following:

[CATransaction begin]; 
[CATransaction setValue: (id) kCFBooleanTrue forKey: kCATransactionDisableActions];
layer.position = CGPointMake(x, y);
[CATransaction commit];

Solution 2 - Ios

Swift 3 Extension :

extension CALayer {
    class func performWithoutAnimation(_ actionsWithoutAnimation: () -> Void){
        CATransaction.begin()
        CATransaction.setValue(true, forKey: kCATransactionDisableActions)
        actionsWithoutAnimation()
        CATransaction.commit()
    }
}

Usage :

CALayer.performWithoutAnimation(){
    someLayer.position = newPosition
}

Solution 3 - Ios

You can also use the convenience function

[CATransaction setDisableActions:YES] 

as well.

Note: Be sure to read the comments by Yogev Shelly to understand any gotchas that could occur.

Solution 4 - Ios

As others have suggested, you can use CATransaction.
The problem comes arises because CALayer has a default implicit animation duration of 0.25 seconds.

Thus, an easier (in my opinion) alternative to setDisableActions is to use setAnimationDuration with a value of 0.0.

[CATransaction begin];
[CATransaction setAnimationDuration:0.0];
layer.position = CGPointMake(x, y);
[CATransaction commit];

Solution 5 - Ios

Combining previous answers here for Swift 4, to clearly make the animation duration explicit...

extension CALayer
{
    class func perform(withDuration duration: Double, actions: () -> Void) {
        CATransaction.begin()
        CATransaction.setAnimationDuration(duration)
        actions()
        CATransaction.commit()
    }
}

Usage...

CALayer.perform(withDuration: 0.0) {
            aLayer.frame = aFrame
        }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMelView Question on Stackoverflow
Solution 1 - IosBen GottliebView Answer on Stackoverflow
Solution 2 - IosCryingHippoView Answer on Stackoverflow
Solution 3 - IosBiclopsView Answer on Stackoverflow
Solution 4 - IosSo Over ItView Answer on Stackoverflow
Solution 5 - IosGilesView Answer on Stackoverflow