Ever since the mind-blowing Protocol-Oriented Programming in Swift WWDC Session, I’ve been thinking a lot about using protocols. But in reality, I haven’t really been using them as much. I’m still digesting what protocol-oriented programming means, and where in my code I should be using it instead of my other go-to programming patterns.

So I was very excited where a HUGE use-case came to mind. MVVM! I already use MVVM – see my earlier MVVM blog post if you’d like to learn more. And adding in protocol-oriented just clicks here!

I’m going to use a very simple example. A Settings screen that currently only has one settings – put your app in Minion Mode!, but you can of course extrapolate to multiple settings:

The View Cell

A cell that has a label and switch button is very generic. You can use this same cell in multiple places – a “Remember Me” setting on a Sign-In screen comes to mind for example. So you want to keep it as a generic view.

A Big Configure

Usually, I use a configure method in my cell that keeps track of all the possible settings different parts of my app that use that cell need. So it would look something like this:

Swift

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

classSwitchWithTextTableViewCell: UITableViewCell{

@IBOutlet private weakvarlabel:UILabel!

@IBOutlet private weakvarswitchToggle:UISwitch!

typealiasonSwitchToggleHandlerType=(switchOn:Bool)->Void

private varonSwitchToggleHandler:onSwitchToggleHandlerType?

overridefuncawakeFromNib(){

super.awakeFromNib()

}

funcconfigure(withTitle title:String,

switchOn:Bool,

onSwitchToggleHandler:onSwitchToggleHandlerType?=nil)

{

label.text=title

switchToggle.on=switchOn

self.onSwitchToggleHandler=onSwitchToggleHandler

}

@IBAction funconSwitchToggle(sender:UISwitch){

onSwitchToggleHandler?(switchOn:sender.on)

}

}

With Swift’s default parameters, adding additional settings to the configure method without breaking all the other places in your code that uses is super simple. For example, when a designer comes and says that the switch color should be different, I just add that as a default parameter:

Swift

1

2

3

4

5

6

7

8

9

10

11

12

funcconfigure(withTitle title:String,

switchOn:Bool,

switchColor:UIColor=.purpleColor(),

onSwitchToggleHandler:onSwitchToggleHandlerType?=nil)

{

label.text=title

switchToggle.on=switchOn

// color option added!

switchToggle.onTintColor=switchColor

self.onSwitchToggleHandler=onSwitchToggleHandler

}

While this might not seem like a big deal in this case, in reality, my configure methods become super long and complicated over time! This is where the cool Protocol-Oriented way comes into play…

The Protocol-Oriented Way

Swift

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

protocolSwitchWithTextCellProtocol{

vartitle: String{get}

varswitchOn: Bool{get}

varswitchColor: UIColor{get}

funconSwitchTogleOn(on:Bool)

}

classSwitchWithTextTableViewCell: UITableViewCell{

@IBOutlet private weakvarlabel:UILabel!

@IBOutlet private weakvarswitchToggle:UISwitch!

private vardelegate:SwitchWithTextCellProtocol?

overridefuncawakeFromNib(){

super.awakeFromNib()

}

funcconfigure(withDelegate delegate:SwitchWithTextCellProtocol){

self.delegate=delegate

label.text=delegate.title

switchToggle.on=delegate.switchOn

}

@IBAction funconSwitchToggle(sender:UISwitch){

delegate?.onSwitchTogleOn(sender.on)

}

}

And what happens when the designer wants to add the ability to change the default color? This is where the magic of protocol extensions comes into play!

Swift

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

extensionSwitchWithTextCellProtocol{

// set the default color here!

varswitchColor: UIColor{

return.purpleColor()

}

}

classSwitchWithTextTableViewCell: UITableViewCell{

// truncated, see above

funcconfigure(withDelegate delegate:SwitchWithTextCellProtocol){

self.delegate=delegate

label.text=delegate.title

switchToggle.on=delegate.switchOn

// color option added!

switchToggle.onTintColor=delegate.switchColor()

}

}

The protocol extension implements the default switchColor option, so anyone who has already implemented this protocol or doesn’t care about setting a color, doesn’t need to worry about it. Only the new cell that has the one different color can implement it.

The ViewModel

So now, the rest is easy. I’m simply going to have a ViewModel for my MinionMode Setting cell:

Swift

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

importUIKit

structMinionModeViewModel: SwitchWithTextCellProtocol{

vartitle="Minion Mode!!!"

varswitchOn=true

varswitchColor: UIColor{

return.yellowColor()

}

funconSwitchTogleOn(on:Bool){

ifon{

print("The Minions are here to stay!")

}else{

print("The Minions went out to play!")

}

}

}

The ViewController

The final step is to pass my view model to the cell when configuring the cell in the ViewController:

With protocol extensions, protocol-oriented programming is starting to make a lot of sense and I’m looking forward to figuring out ways to use it more! You can get the full code sample on Github here.

UPDATE: Separating the Data Source and the Delegate

In the comments below, Marc Baldwin suggested separating out the cell’s data source and delegate into two protocols, just like UITableView does, and I LOVE that idea. Here is what that would look like:

The View Cell

The cell would have two protocols, and it could be configured with both: