Recently I’ve been exploring Swift and really been enjoying both the syntax and extension points. Although still getting my legs under me with Swift and interface builder it has been a great deal of fun. For a recent project, I had to provide a subtle progress cue when the application was synchronizing information. This cue was accomplished by simply replacing the UIImage of our existing UIImageView, then rotating the UIImageView using CABasicAnimation. The below shows the end result in action.
Rotation Extension – UIView+Rotation.swift
A majority of the logic behind this rotation effect is encapsulated in the UIView+Rotation extension class shown below. The following shows the full extension method. You can also view the extension method on github here.
extension UIView { func startRotating(duration: Double = 1) { let kAnimationKey = "rotation" if self.layer.animationForKey(kAnimationKey) == nil { let animate = CABasicAnimation(keyPath: "transform.rotation") animate.duration = duration animate.repeatCount = Float.infinity animate.fromValue = 0.0 animate.toValue = Float(M_PI * 2.0) self.layer.addAnimation(animate, forKey: kAnimationKey) } } func stopRotating() { let kAnimationKey = "rotation" if self.layer.animationForKey(kAnimationKey) != nil { self.layer.removeAnimationForKey(kAnimationKey) } } }
Start Rotating
The first step in starting the rotation animation is to replace the existing UIImage with the one we will be animating. In our case we do this by loading an image from our Asset Catalog, as shown below.
syncImage.image = UIImage(named:”sync-spinning”)
Next, since we have the UIView+Rotation extension method added to your project, you simply have to call the startRotating method on your UIImageView to start animating the UIImageView. The following shows how to call the startRotating extension method.
syncImage.startRotating();
In our example project, we have encapsulated this into the startSpinning shown below.
func startSpinning() { syncImage.image = UIImage(named:"sync-spinning") syncImage.startRotating() }
Stop Rotating
The process of stopping the animation is similar to that of starting the rotation process. First we stop the rotation animation of the UIImageView by calling the stopRotating extension method as shown below.
syncImage.stopRotating()
Next, we replace the UIImage with our initial non rotating image. As shown below we do this by loading an image from the Asset Catalog.
syncImage.image = UIImage(named:”sync-not-spinning”)
In our example project, we have encapsulated this into the stopSpinning shown below.
func stopSpinning() { syncImage.stopRotating() syncImage.image = UIImage(named:"sync-not-spinning") }
Ok, so show me the code
The following shows the code used to call both the start and stop rotating animations. For demonstration purposes, a delay is added to trigger the stop rotating event to illustrate the full animation life cycle.
func startSpinning() { syncImage.image = UIImage(named:"sync-spinning") syncImage.startRotating() } func stopSpinning() { syncImage.stopRotating() syncImage.image = UIImage(named:"sync-not-spinning") } func handleSyncTap(sender: UITapGestureRecognizer? = nil) { startSpinning() let dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(3 * Double(NSEC_PER_SEC))) dispatch_after(dispatchTime, dispatch_get_main_queue(), { self.stopSpinning() }) }
A full working example of how to create a rotating UIImageView is available on github at https://github.com/benbahrenburg/SpinningImageView-Example
Walk Through
The following video tutorial walks through the UIImageView rotation example in great detail outlining everything from how the Storyboard UI elements are created through the UIGestureRecognizers added to trigger the rotation animations.
