I am confused about What's the difference between isRemovedOnCompletion and kCAFillModeForwards in Layer animation. I am reading a book about animation which suggesting using only kCAFillModeForwards to keep last frame presented.
But it didn't work with me so I did a search and I can see others suggesting combining kCAFillModeForwards and isRemovedOnCompletion to keep last frame presented. Last solution worked with me, but I am still confused, what's the difference between them?

- 4,083
- 3
- 28
- 50
-
@matt thanks for replaying, but why both properties are exist if I need to reset animated property manually? – Dot Freelancer Oct 21 '18 at 12:00
-
@matt thanks for attaching the link, I got it now. – Dot Freelancer Oct 21 '18 at 12:05
-
@matt why? it may help someone else, because I see too many using both isRemovedOnCompletion and kCAFillModeForwards instead of replacing animated view properties. – Dot Freelancer Oct 21 '18 at 12:40
-
https://stackoverflow.com/a/13965508/77567 – rob mayoff Oct 21 '18 at 18:40
1 Answers
You should not misuse isRemovedOnCompletion
or kCAFillModeForwards
for this purpose. I have seen this book and many examples use this "trick", but it is wrong. It is one of the worst misinformational memes ever to get promulgated around the Internet! It's just a crutch to make up for the fact that you have constructed the animation incorrectly.
For example, consider this simple code:
let opts : UIView.AnimationOptions = .autoreverse
let xorig = self.v.center.x
UIView.animate(withDuration:1, delay: 0, options: opts, animations: {
self.v.center.x += 100
}, completion: nil
)
The view animates 100 points to the right and then animates 100 points back to its original position — and then jumps 100 points back to the right. The reason is that the last actual value we assigned to the view's center x
is 100 points to the right, so when the animation is over and the "animation movie" is whipped away, the view is revealed still sitting 100 points to the right.
The solution is to move the view back to its original position, yourself! You can do that in the completion:
function:
let opts : UIView.AnimationOptions = .autoreverse
let xorig = self.v.center.x
UIView.animate(withDuration:1, delay: 0, options: opts, animations: {
self.v.center.x += 100
}, completion: { _ in
self.v.center.x = xorig
})
All misuses of kCAFillModeForwards
and isRemovedOnCompletion
are based on a failure to do that sort of thing. Either in view animation or explicit layer animation, the programmer has neglected to give the animated property the value that it will have at the end of the animation. So what the confused programmer then does is cheat, sweeping the problem under rug. kCAFillModeForwards
means "keep the animation at its endpoint when it ends". Setting isRemovedOnCompletion
to false
means that the animation never ends! That is a terrible idea; it puts an unnecessary strain on the rendering engine, and it is completely misguided and unnecessary. Basically you are covering the real position of the view/layer with the animation position. That is wrong. Never follow those examples. Learn how to write an animation correctly and do so.

- 515,959
- 87
- 875
- 1,141