Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Rotatable: A Swift Protocol Extension to Rotate Any UIView

DZone's Guide to

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
Free Resource

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

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.


Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

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.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}