Daniel Galasko Daniel Galasko - 1 year ago 129
iOS Question

In Swift, how can I declare a variable of a specific type that conforms to one or more protocols?

In Swift I can explicitly set the type of a variable by declaring it as follows:

var object: TYPE_NAME

If we want to take it a step further and declare a variable that conforms to multiple protocols we can use the

var object: protocol<ProtocolOne,ProtocolTwo>//etc

What if I would like to declare an object that conforms to one or more protocols and is also of a specific base class type? The Objective-C equivalent would look like this:

NSSomething<ABCProtocolOne,ABCProtocolTwo> * object = ...;

In Swift I would expect it to look like this:

var object: TYPE_NAME,ProtocolOne//etc

This gives us the flexibility of being able to deal with the implementation of the base type as well as the added interface defined in the protocol.

Is there another more obvious way that I might be missing?


As an example, say I have a
factory that is responsible for returning cells conforming to a protocol. We can easily setup a generic function that returns cells conforming to a protocol:

class CellFactory {
class func createCellForItem<T: UITableViewCell where T:MyProtocol >(item: SpecialItem,tableView: UITableView) -> T {

later on I want to dequeue these cells whilst leveraging both the type and the protocol

var cell: MyProtocol = CellFactory.createCellForItem(somethingAtIndexPath) as UITableViewCell

This returns an error because a table view cell does not conform to the protocol...

I would like to be able to specify that cell is a
and conforms to the
in the variable declaration?


If you are familiar with the Factory Pattern this would make sense in the context of being able to return objects of a particular class that implement a certain interface.

Just like in my example, sometimes we like to define interfaces that make sense when applied to a particular object. My example of the table view cell is one such justification.

Whilst the supplied type does not exactly conform to the mentioned interface, the object the factory returns does and so I would like the flexibility in interacting with both the base class type and the declared protocol interface

Answer Source

You cannot declare variable like

var object:Base,protocol<ProtocolOne,ProtocolTwo> = ...

nor declare function return type like

func someFunc() -> Base,protocol<MyProtocol,Protocol2> { ... }

You can declare as a function parameter like this, but it's basically up-casting.

func someFunc<T:Base where T:protocol<MyProtocol1,MyProtocol2>>(val:T) {
    // here, `val` is guaranteed to be `Base` and conforms `MyProtocol` and `MyProtocol2`

class SubClass:BaseClass, MyProtocol1, MyProtocol2 {

let val = SubClass()

As of now, all you can do is like:

class CellFactory {
    class func createCellForItem(item: SpecialItem) -> UITableViewCell {
        return ... // any UITableViewCell subclass

let cell = CellFactory.createCellForItem(special)
if let asProtocol = cell as? protocol<MyProtocol1,MyProtocol2> {

With this, technically cell is identical to asProtocol.

But, as for compiler, cell has interface of UITableViewCell only, while asProtocol has only protocols interface. So, when you want to call UITableViewCell's methods, you have to use cell variable. When you want to call protocols method, use asProtocol variable.

If you are sure that cell conforms to protocols you don't have to use if let ... as? ... {}. like:

let cell = CellFactory.createCellForItem(special)
let asProtocol = cell as protocol<MyProtocol1,MyProtocol2>
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download