Over a million developers have joined DZone.

Rotatable: A Swift Protocol Extension to Rotate Any UIView

How to create your own protocol to allow rotations for your views without duplicating code

· Mobile Zone

One of the questions frequently asked on StackOverflow is “how do I rotate my UILabel / UIButton / UISlider etc.” So, following on from Blurable, my Swift protocol extension for applying a Gaussian blur to UIViews, I thought I’d create another quick extension to make any UIView rotatable

By default, UIViews don’t have a simple rotation property. To rotate them, you have to create a CGAffineTransform and pass it to the view’s transform property. If your user interface requires lots of rotating, Rotatable bundles all that up into a separate extension and lets you forget about the implementation details.

The Rotatable Protocol

The protocol itself is pretty basic, consisting of one property, transform of type CGAffineTransform, which UIViews already have, two new methods for actually rotating:

  mutating func rotate(degrees degrees: CGFloat, animated: Bool)
  mutating func rotate(radians radians: CGFloat, animated: Bool)

…and a readonly property that returns a tuple of the UIView’s current rotation in both radians and degrees:

var rotation: (radians: CGFloat, degrees: CGFloat) { get }

Rotatable Mechanics

The protocol extension contains the mechanics for rotating the component. It’s pretty basic stuff, simply creating aCGAffineTransformMakeRotation and  applying it to the transform property, If the rotate() method is called with animated set to true, it wraps setting in a UIView.animateWithDuration:

 mutating func rotate(radians radians: CGFloat, animated: Bool = false)
    {
        if animated
        {
            UIView.animateWithDuration(0.2)
            {
                self.transform = CGAffineTransformMakeRotation(radians)
            }
        }
        else
        {
            transform = CGAffineTransformMakeRotation(radians)
        }
    }

To return the current rotation, I extract the angle from the CGAffineTransform:      

   var rotation: (radians: CGFloat, degrees: CGFloat)
    {
        let radians = CGFloat(atan2f(Float(transform.b), Float(transform.a)))

        return (radians, radiansToDegrees(radians))
    }

Implementation

All the code for Rotatable is in one file, Rotatable.swift. To rotate an object, let’s say a date picker, all you have to do is invoke therotate() method:    

 var datePicker = UIDatePicker()
 view.addSubview(datePicker)

 datePicker.rotate(degrees: 45)

If you’re resetting the rotation, you may want to animate it, in which case the syntax would be:

datePicker.rotate(radians: 0, animated: true)

By default, the animated property is set to false.

One little caveat - Rotatable doesn't work too well in a UIStackView, all the examples in my demo are absolutely positioned. 

Conclusion

Hopefully, this projects is another good demonstration of how Swift’s protocol extensions allow developers to retroactively add almost any type of behaviour to all objects in Swift, including visual components, with a minimum of effort.

All the code to this project is available in my GitHub repository here.


Topics:
swift

Published at DZone with permission of Simon Gladman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}