使用CGAffineTransform旋转视图仅首次生效,后续无动画如何解决?
解决自定义视图重复旋转动画失效及应用冻结问题
问题根源
你当前代码存在两个核心问题:
- 动画触发条件缺失:每次动画都将视图的
transform重置为「相对于原始状态旋转90度」,第一次旋转后视图的transform已经是这个值,后续再设置相同的属性值,UIKit检测不到变化,自然不会触发动画。 - 高频递归阻塞主线程:由于动画未实际执行,
completion闭包会立刻触发,导致_rotateSelf()被高频递归调用,最终阻塞主线程造成应用冻结。
修正后的代码
private func _rotateSelf(duration: Double = 1.0, delay: Double = 3.0) { print("self._rotateSelf() called from UICustomView") UIView.animate(withDuration: duration, delay: delay, options: [.curveEaseInOut], animations: { // 在上一次的旋转状态基础上继续旋转90度 self.transform = self.transform.rotated(by: .pi / 2) }, completion: { finished in if finished { print("Animation finished") self._rotateSelf() } }) }
关键修改说明
将CGAffineTransform.identity.rotated(by: .pi/2)改为self.transform.rotated(by: .pi/2),每次旋转都基于视图当前的transform状态叠加90度,确保transform属性每次都有有效变化,UIKit会正常触发动画。同时,动画真正完成后才会递归调用,避免了高频递归导致的主线程阻塞。
可选优化方案(避免递归)
如果需要更灵活地控制旋转启停,推荐使用定时器替代递归:
private var rotationTimer: Timer? // 启动旋转 func startRotating() { rotationTimer = Timer.scheduledTimer(withTimeInterval: 3.0, repeats: true) { [weak self] _ in guard let self = self else { return } UIView.animate(withDuration: 1.0, options: .curveEaseInOut) { self.transform = self.transform.rotated(by: .pi / 2) } } } // 停止旋转 func stopRotating() { rotationTimer?.invalidate() rotationTimer = nil }
内容的提问来源于stack exchange,提问作者user4496950
相关产品推荐
相关产品推荐

