我有一个按钮,当它被点击时,它应该自行旋转,这是我的代码:
@IBAction func calculateButtonTapped(_ sender: UIButton) {
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotateAnimation.fromValue = 0.0
rotateAnimation.toValue = CGFloat(M_PI)
rotateAnimation.speed = 3.0
rotateAnimation.repeatCount = 6000
calculateButton.layer.add(rotateAnimation, forKey: nil)
DispatchQueue.main.async {
self.openCircle(withCenter: sender.center, dataSource: self.calculator!.iterateWPItems())
self.calculateButton.layer.removeAllAnimations()
}
}
然而,有时当我点击按钮时,它立即返回到正常状态然后旋转,有时按钮变为暗选择状态,并且根本没有动画,动画完成后的任务。如果我没有停止动画,它会在openCircle
完成后启动。
可能是什么原因?
答案 0 :(得分:0)
duration
。
替换此
rotateAnimation.speed = 3.0
用这个
rotateAnimation.duration = 3.0
@alexburtnik,可以阻止主线程
不,它不好。您应该在completion
方法中添加openCircle
参数,并在动画(或其他)完成时调用它。如果你阻止主线程,你将有一个冻结的UI,强烈建议不要这样做。
calculateButtonTapped
,那么您也应该调度方法的第一部分。与UI 相关的所有内容必须在主线程上完成。看起来应该类似于:
@IBAction func calculateButtonTapped(_ sender: UIButton) {
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotateAnimation.fromValue = 0.0
rotateAnimation.toValue = CGFloat(M_PI)
rotateAnimation.duration = 3.0
rotateAnimation.repeatCount = .infinity //endless animation
calculateButton.layer.add(rotateAnimation, forKey: nil)
self.openCircle(
withCenter: sender.center,
dataSource: self.calculator!.iterateWPItems(),
completion: {
self.calculateButton.layer.removeAllAnimations()
})
}
func openCircle(withCenter: CGPoint, dataSource: DataSourceProtocol, completion: (()->Void)?) {
//do your staff and call completion when you're finished
//don't block main thread!
}
答案 1 :(得分:0)
尝试此操作以通过将按钮连接到故事板上的操作来旋转单击的按钮。您当然可以通过传递任何UIButton作为发件人来调用此函数!
@IBAction func calculateButtonTapped(_ sender: UIButton) {
guard (sender.layer.animation(forKey: "rotate") == nil) else { return }
let rotationDuration: Float = 3.0
let animation = CABasicAnimation(keyPath: "transform.rotation")
animation.toValue = Float.pi * rotationDuration
animation.duration = CFTimeInterval(rotationDuration)
animation.repeatCount = .infinity
sender.layer.add(animation, forKey: "rotate")
}
将rotationDuration
更改为完整旋转所需的任何时间长度。您还可以进一步调整该函数以将其作为参数。
修改:添加了一条警卫声明,以便每次按下该按钮时轮换都不会累加。
答案 2 :(得分:0)
感谢大家的回答,我在多线程的速成课程后自己找到了解决方案,问题是我用openCircle
方法阻止了主线程。
这是更新后的代码:
@IBAction func calculateButtonTapped(_ sender: UIButton) {
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotateAnimation.fromValue = 0.0
rotateAnimation.toValue = CGFloat(M_PI)
rotateAnimation.speed = 3.0
rotateAnimation.repeatCount = .infinity
DispatchQueue.global(qos: .userInitiated).async {
self.openCircle(withCenter: sender.center, dataSource: self.calculator!.iterateWPItems()){}
DispatchQueue.main.sync {
self.calculateButton.layer.removeAllAnimations()
}
}
self.calculateButton.layer.add(rotateAnimation, forKey: nil)
}