How to declare Swift protocol for a specific class

Swift Protocol

A protocol defines a blueprint of methods, properties, and other requirements. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements.

But there would be a time when you want to restrict protocols to be adopted by a specific class. In Swift 5, you can do just that.

Syntax #

You have two ways to declare this.

protocol MyViewController: UIViewController { /*...*/ }

protocol MyViewController where Self: UIViewController { /*...*/ }

This syntax makes a protocol constrain their conforming types to a subclass (or is a type) of UIViewController.

Error #

If you try to adopt this protocol from non UIViewController subclass, you will get an error.

class Foo: MyViewController {}
// 'MyViewController' requires that 'Foo' inherit from 'UIViewController'

Benefits #

Declare your protocol like this is semantically equivalent to a class existential of UIViewController & MyViewController. That's mean you can access both members of the class and requirements of the protocol.

protocol MyViewController: UIViewController {
func foo()
}

class Example: UIViewController {
var myViewController: MyViewController?

override func viewDidLoad() {
super.viewDidLoad()

myViewController?.foo()
myViewController?.title = "Foo"
}
}

In the above example, you can access a view controller title and foo() method from the MyViewController protocol.

Extension #

You can also use this syntax with a protocol extension. Which will add default Implementations just for the specified class.

protocol P {
func foo()
}
extension P where Self: UIViewController {
func foo() {
print("You can reference UIViewController property here: \(view)")
}
}

The above example will add a default implementation of foo() for any subclass of UIViewController that conform to P protocol.

// No error
class ViewController: UIViewController, P {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
foo()
}
}

// Type 'Struct' does not conform to protocol 'P'
struct Struct: P {}

Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading and see you next time.

If you enjoy my writing, please check out my Patreon https://www.patreon.com/sarunw and become my supporter. Sharing the article is also greatly appreciated.

Become a patron Tweet Share

If you enjoy this article, you can subscribe to the weekly newsletter.

Every Friday, you’ll get a quick recap of all articles and tips posted on this site — entirely for free.

← Home