Search code examples
swiftgenericsprotocols

Protocols with generic parameter types


I'm trying to create a protocol which accept objects that are subclassed from NSObject:

protocol ProtocolExample {
    func willDisplay<T: NSObject>(object: T?)
}


class TableViewCell: UITableViewCell,ProtocolExample {  
    func willDisplay<T>(object: T?) where T : NSObject {

    }

    func willDisplay(object: AMDObject?) {

    }
}

class AMDObject: NSObject {}

So my question is how can I apply that I only need to add the second willDisplay method instead of the first. How can I tell that in that case of tableviewcell my T is currently AMDObject type (like T is now AMDObject)


Solution

  • The signature of the requirement in ProtocolExample should be read to mean, "a function willDisplay which accepts object, a parameter which can be of any (optional) type T? as long as T inherits from NSObject". This definition guarantees that I could write a function like this:

    func displayThings(in example: ProtocoExample) {
        example.willDisplay(NSArray())
        example.willDisplay(NSObject())
    }
    

    However, with your implementation, what would happen if I wrote:

    let cell: TableViewCell = // ...
    displayThings(in: cell)
    

    Then, displayThings would be unable to call example.willDisplay(NSArray()) since TableViewCell can only handle willDisplay for and AMDObject.

    If you have control over the protocol yourself, you could implement this with an associatedtype:

    protocol ProtocolExample {
        associatedtype DisplayObject: NSObject
    
        func willDisplay(object: DisplayObject?)
    }
    
    class TableViewCell: UITableViewCell, ProtocolExample {
        // Implicit typealias DisplayObject = AMDObject
        func willDisplay(object: AMDObject?) {
    
        }
    }
    

    Depending on how you are using ProtocolExample, though, adding this associatedtype may not be a straightforward solution.