Im having trouble figuring out why the animation is flickering from the fromValue to the toValue after my animation block is complete. I know that after you complete an anim
To answer your first question
layoutSubviews will only be called once per run-loop. You can call [self setNeedsLayout] as much as you want without worrying about taking a performance hit laying out your views needlessly.
Referenced From: Kubicek, Jim. "Abusing UIView." OCT 11TH, 2012. http://jimkubicek.com/blog/2012/10/11/using-uiview/
To answer your second question, you are right about why it is flickering. The problem is that there is no guarantee that the animationDidStop callback method will be called before the layer's appearance is reset.
There are a couple of ways to fix this, the following way just involves adding some extra code without changing your existing code.
//kCAFillModeForwards: the animatable properties take on the end value once it has finished
[strokeAnimation setFillMode:kCAFillModeForwards];
[strokeAnimation setRemovedOnCompletion:NO];
[fillAnimation setFillMode:kCAFillModeForwards];
[fillAnimation setRemovedOnCompletion:NO];
[group setFillMode:kCAFillModeForwards];
[group setRemovedOnCompletion:NO];
[self.checkmarkLayer addAnimation:group forKey:nil];
When a CAAnimation completes, it removes itself from the layer and causes the layer to reset, so the first thing we will do is stop the animation from being removed.
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
animationCompletionBlock theBlock = [theAnimation valueForKey: kAnimationCompletionBlock];
if (theBlock)
theBlock();
[self.checkmarkLayer removeAllAnimations];
}
When the animationDidStop method is called, we set the layer's properties like before, then we remove the animations from the layer.
One more thing to think about is that when you change a CALayer's appearance, it gets implicitly (automatically) animated. So when you setup the completion block, you want to explicitly tell core animation not to animate
animationCompletionBlock block;
block = ^(void){
[CATransaction begin];
[CATransaction setDisableActions:YES];
[self.checkmarkLayer setFillColor:[UIColor whiteColor].CGColor];
[CATransaction commit];
};