I'm trying to make a simple scale animation of a button 1.0
-> 1.4
, repeat 3 times and then stop, but I'm experiencing a glitch on a real device.
The code below works smoothly on a simulator, but on a real device (iPhone 12 Pro with iOS 16) it glitches and I can see the jump to scale 1.4
after animation is done, and then it jumps to scale 1.0
on completion where I set transform = .identity
.
I've suspected UIView.modifyAnimations
, but the same problem happens with the now deprecated UIView.setAnimationRepeatCount(3)
.
Here is the video of the glitch on the real device: https://i.imgur.com/x1LJ9Ox.mp4
UIView.animate(withDuration: 0.5, delay: 0, animations: {
UIView.modifyAnimations(withRepeatCount: 3, autoreverses: true) {
self.titleButton.transform = CGAffineTransformMakeScale(1.4, 1.4)
// self.titleButton.layoutIfNeeded() // doesn't change anything
}
}, completion: { _ in
self.titleButton.transform = .identity
})
I've tested on my iphone 13 iOS 16, it glitches like you said above.
Maybe I'm wrong or misunderstand something but looks like something is changing in modifyAnimations(withRepeatCount:autoreverses:animations:)
.
In simulator, after the animation in modifyAnimations
is done, it immediately go to completion
. If in completion
do nothing with the view, it will turn back to CGAffineTransformMakeScale(1.4, 1.4)
. But if the view has transform
anything, it will turn to that transform
.
But in real device, after the animation in modifyAnimations
is done, the view will immediately turn back to the final of animation which here is CGAffineTransformMakeScale(1.4, 1.4)
( the simulator doesn't have this step) then after that go to completion
. This cause the glitches like you said.
I have a workaround for this situation
UIView.animate(withDuration: 0.5, animations: {
// stop at the half of the final repeat means no autoreverses accur at the end
UIView.modifyAnimations(withRepeatCount: 2.5, autoreverses: true) {
self.secondView.transform = CGAffineTransformMakeScale(1.4, 1.4)
}
}, completion: { _ in
// make final scale back here
UIView.animate(withDuration: 0.5, animations: {
self.secondView.transform = .identity
})
})