Swift Protocols are awesome. Understanding how they can (or should) fit into our code can be tricky. Today we'll take a baby step into the world of protocols with a simple, but "real" example and try to illustrate the upsides. Let's get started.

We're going to be fancy and abstract away some of our layout code. So we'll create a little struct to hold some layout settings like this:

struct LayoutSettings { let direction : FlexDirection let justification : Justification let alignmentSelf : Alignment let alignmentChildren : Alignment /// ...etc }

See? Fancy. This is great if we want to specify each individual combination each time, but it'd be nice if we could define some sort of "pre-canned" layouts that we could use by name. Sounds like a great job for a Swift Enum.

enum CannedLayout { case FillParent case SizeToFit case Absolute ( point : CGPoint ) case Relative ( closure : ( parentFrame : CGRect ) -> CGSize ) }

Lovely, this will be handy. How are we going to wire all this together though? Simple, we'll make a Protocol that's only responsibility is to convert itself to a LayoutSettings.

protocol LayoutSettingsConvertible { func layoutSettings () -> LayoutSettings }

LayoutSettings can adopt this extremely simply:

extension LayoutSettings : LayoutSettingsConvertible { func layoutSettings () -> LayoutSettings { return self } }

Whew! That was tough.

Making our CannedLayout Enum adopt our new Protocol is a bit more involved, but really just means switch -ing over self and return the proper combination of settings for each case.

extension CannedLayout : LayoutSettingsConvertible { func layoutSettings () -> LayoutSettings { switch self { case . FillParent : return LayoutSettings ( direction : . Vertical , justification : . Start , alignmentSelf : . Stretch , alignmentChildren : . Start ) /// ...etc } } }

All that's left is to use this new protocol somewhere. Let's wire this up to UIView to make it useful:

extension UIView { func layout ( settings : LayoutSettingsConvertible ) { /// configure the view for the new settings here } }

Neat! Now, we can use configure views with one of our canned layouts:

let v = UIView ( frame : . zero ) v . layout ( CannedLayout . FillParent )

But we can also easily configure them the "long way" using a full LayoutSettings object directly:

let v = UIView ( frame : . zero ) v . layout ( LayoutSettings ( direction : . Vertical , justification : . Start , alignmentSelf : . Stretch , alignmentChildren : . Start ))

Now that we have this simple protocol, we can make other helper types like this:

struct Row : LayoutSettingsConvertible { func layoutSettings () -> LayoutSettings { return LayoutSettings ( direction : . Horizontal , justification : . Start , alignmentSelf : . Stretch , alignmentChildren : . Start ) } }

That's just the basics when it comes to Protocols. They have much more to offer. More on this topic soon!