Forced to cast, even if protocol requires given type

Adopting the protocol Fooable tells the compiler that this particular UIViewController responds to foo(), no less no more.

In reverse conclusion Fooable does not become UIViewController necessarily.

The constraint Self: UIViewController is just another information for the compiler to complain at compile time if the affected class is not UIViewController

In your case when annotating SampleViewController to Fooable the compiler knows only that SampleViewController responds to foo(). It does not know that the type is actually a subclass of UIViewController.

So do not annotate a concrete class to a protocol if you want to access properties of the concrete class.

However you could add the show method and other common properties / methods to the protocol

protocol Fooable: class where Self: UIViewController {
    func foo()
    func show(_ vc: Fooable, sender: Any?)
}

then you can use Fooable because the compiler knows that the type adopting the protocol responds to the method.


A suitable practice to annotate a type to a protocol is for example when you are going to create a heterogenous but restricted collection type

let array : [CustomStringConvertible] = ["Foo", 1, false]
array.forEach{ print("\($0)")}

The code prints the three items using the description property which all items respond to. The compiler recognizes the three items as types which have a description property, not as String, Int and Bool.

Update:

In Swift 5 support of superclass constrained protocols is implemented.

Leave a Comment