Using typealias With Protocols

In this article, I’ll discuss a cool technique for adding required protocol conformance to a subclass using Swift and Xcode.

13 August 2018
About a 3 minute read.

A common use case for a UIPickerView, or any dropdown type control in fact, is to have an id field and a caption. When a user activates the control, it would be great to scroll the list in the picker to the row that has the existing value (in the case of updating or even creating when he/she leaves the field and comes back).

Let’s look at this example:

Colors:

ID Color
1 Red
2 Orange
3 Yellow
4 Green
5 Blue
6 Indigo
7 Violet

If we have an entry previously saved with id = 4 (Green), then the user comes back to edit, we should scroll the picker to Green. The UIPickerView doesn’t give us a way to do this easily. Wouldn’t it be cool if we could extend the control to pass in an id and scroll that way? Sure it would! However, the implementation of this will vary based on the type of data we’re dealing with.

In instances where implementation will vary, and there’s a default implementation, it’s easy. Just create a func with the default code, and allow subclasses to override it.

That’s not our situation this time though. There’s no default way to implement this. This is where a protocol comes to the rescue. But we have to do a little typealias trick to make it work the way we want.

Let’s call our new class IDPickerView. Now instead of just inheriting from UIPickerView, we actually need to inherit from a UIPickerView and a protocol. We actually also want to add a couple of properties to it at the same time. Here’s our code, all in a file called IDPickerView.swift

1
2
3
4
5
6
7
8
9
10
11
12
13
import UIKit

protocol IDPickerViewProtocol {
  func selectRowWith(_ id: Int)
}

typealias IDPickerView = IDPickerViewClass & IDPickerViewProtocol

class IDPickerViewClass: UIPickerView {
  // Properties    
  var textField: UITextField?
  var id = 0
}

Here’s an explanation.

  • Line 1: Obviously we need to import UIKit for the UIPickerView

  • Lines 3-5: We define a protocol with a requirement that selectRowWith(id:) be implemented.

  • Lines 9-13: Then we create the subclass IDPickerViewClass and add two new properties.

  • Line 7: Backing up a little bit, we create a typealias that combines a UIPickerView subclass, and the protocol.

To use it, just create a class of type IDPlacePIckerView. The compiler will require the creation of selectRowWith(id:) and Xcode will even give a quick fix to stub it out for you. Sweet!

There’s more than one way to skin this cat, but this way works well since you don’t have to, say for example, create a delegate and conform to its protocol. You’re still having to do that with the UIPickerViewDelegate anyway, so this would just be one more if we didn’t package it up neatly this way. I like that we get cleaner code, and compile time checks. Other techniques I’ve seen people use would be to throw a fatalError() at runtime if the default implementation isn’t overridden. I’d rather catch the omission at compile time.

While I’ve illustrated this technique with the UIPickerView, which is the first time I’ve used it, I plan to apply this to other situations as appropriate.


by:
David Lari

https://davidlari.com
Interests: programming, writing, science, history. You might also find me playing some PC Games.