9

Here is my code. Intent is to continuously rotate the UIImageView named swirls[l]. However, there is a small pause between every rotation start/end. I have gone through every single animation tutorial but cant figure out what the mistake is?

let fullRotation = CGFloat(M_PI * 2)

    let duration = 2.0
    let delay = 0.0
    let options = UIViewKeyframeAnimationOptions.Repeat | UIViewKeyframeAnimationOptions.CalculationModeLinear

    UIView.animateKeyframesWithDuration(duration, delay: delay, options: options, animations: {
        UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 1/3, animations: {
            swirls[l].transform = CGAffineTransformMakeRotation(1/3 * fullRotation)
        })
        UIView.addKeyframeWithRelativeStartTime(1/3, relativeDuration: 1/3, animations: {
            swirls[l].transform = CGAffineTransformMakeRotation(2/3 * fullRotation)
        })
        UIView.addKeyframeWithRelativeStartTime(2/3, relativeDuration: 1/3, animations: {
            swirls[l].transform = CGAffineTransformMakeRotation(3/3 * fullRotation)
        })

        }, completion: {finished in 
    })

EDIT: I see that it has been suggested that a previous solution is available, but it simply does not work for continuous uninterrupted rotation. The only trick that worked for me is the answer that I chose below. Thanks

Kashif
  • 4,642
  • 7
  • 44
  • 97
  • possible duplicate of [Create a continuously rotating square on the screen using animateKeyframesWithDuration](http://stackoverflow.com/questions/26665124/create-a-continuously-rotating-square-on-the-screen-using-animatekeyframeswithdu) – Zell B. Mar 10 '15 at 17:29

3 Answers3

56

Try below extension for swift 4.

extension UIView {
    func rotate360Degrees(duration: CFTimeInterval = 3) {
        let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
        rotateAnimation.fromValue = 0.0
        rotateAnimation.toValue = CGFloat(Double.pi * 2)
        rotateAnimation.isRemovedOnCompletion = false
        rotateAnimation.duration = duration
        rotateAnimation.repeatCount=Float.infinity
        self.layer.add(rotateAnimation, forKey: nil)
    }
}

For start rotation.

MyView.rotate360Degrees()

And for Stop.

MyView.layer.removeAllAnimations()

You can use UIButton, UILabel and many more.

wm.p1us
  • 2,019
  • 2
  • 27
  • 38
Keval Vadoliya
  • 1,003
  • 1
  • 9
  • 17
19

I'm not sure what's wrong with your code, but I've implemented continuous rotation using this method,

@IBAction func rotateView(sender: UIButton) {
    UIView.animate(withDuration: 0.5, delay: 0, options: .curveLinear, animations: { () -> Void in
        self.spinningView.transform = self.spinningView.transform.rotated(by: .pi / 2)
    }) { (finished) -> Void in
        self.rotateView(sender: sender)
    }
}
Karen Hovhannisyan
  • 1,140
  • 2
  • 21
  • 31
rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • 3
    I think it would be better to use UIViewAnimationOptions.Repeat rather then starting animation again in completion handler – Zell B. Mar 10 '15 at 15:59
  • 2
    @zellb, that doesn't work in this situation since I'm only going 1/4 of the way around with each call. Besides, that's what the OP is doing, and it results in a delay before the next animation starts. – rdelmar Mar 10 '15 at 16:01
  • @rdelmar: I tried this but I get no rotation at all. – Kashif Mar 11 '15 at 22:18
  • @TPos, I don't know why that would be without seeing how you implemented it. It works fine in my hands. – rdelmar Mar 11 '15 at 23:25
  • @rdelmar: Actually your method does work!! I had initially made a typo. – Kashif Mar 11 '15 at 23:52
  • I did exactly same thing except the "options: .curveLinear" part which actually did the trick. – Artin Feb 18 '22 at 20:37
5

If you want to continuous rotate Button or View and stop that rotation whenever you want then you can try this: For start rotation:

@IBOutlet weak var RotateBtn: UIButton!
var timeTimer: Timer?

viewDidLoad()
{
  self.rotateView()
  timeTimer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(self.rotateView), userInfo: nil, repeats: true)
}

func rotateView()
{
    UIView.animate(withDuration: 0.5, delay: 0, options: .curveLinear, animations: { () -> Void in
        self.RotateBtn.transform = self.RotateBtn.transform.rotated(by: CGFloat(M_PI_4))
    })
}

If you want to stop rotation then use:

@IBAction func StopBtn_Pressed(_ sender: AnyObject)
{
   timeTimer?.invalidate()
   self.RecordBtn.layer.removeAllAnimations()
} 
Pragnesh Vitthani
  • 2,532
  • 20
  • 28