naglerrr
naglerrr

Reputation: 2854

Swift Generics and Protocol Extensions

I have a protocol Reusablethat has a static function static func reuseId() -> String and a protocol extension that defines the default implementation for the function. Then, I implemented a extension on UITableViewCell to conform to the Reusable protocol. I can now use the function on my TableViewCells without a problem: SomeTableViewCell.reuseId().

The Problem I have is with Generics. I have a generic class that has a generic parameter of the type UITableViewCell:

internal class SomeClass<CellType: UITableViewCell>: NSObject { 
    ...
}

I want to be able to use the function specified in Reusable in my generic class on CellType but unfortunately this does not work as expected. The compiler always generates the error Type 'CellType' has no member 'reuseId'.

Does anybody know why this is happening? Is there a workaround?

I am using Xcode 7.0 with Swift 2.0.

Greetings from Germany

UPDATE: Here is some sample code that better shows my problem:

import UIKit

protocol Reusable {
    static func reuseId() -> String
}

extension Reusable {
    static func reuseId() -> String {
        return String(self).componentsSeparatedByString(".").last!
    }
}

extension UITableViewCell: Reusable { }

class SomeGenericClass<CellType: UITableViewCell> {
    func someFunction() {
        let reuseIdentifier = CellType.reuseId()
    }
}

This Code will generate the above error but I do not quite understand why this happens. I think the main difference to the sample code that jtbandes posted is that I use a static function.


UPDATE: The issue is fixed in Xcode 8.3 beta 2. The sample code above now works as expected (after migrating it to Swift 3 of course).

Upvotes: 0

Views: 600

Answers (2)

Benzi
Benzi

Reputation: 2459

Another (workaround) way to get what you need:

class GenericExample<CellType:UITableViewCell where CellType:Reusable>     
{
    func test() -> String {
        return CellType.reuseId()
    }
}

GenericExample<UITableViewCell>().test() // returns "UITableViewCell"
GenericExample<MyCell>().test() // returns "MyCell"

Upvotes: 0

jtbandes
jtbandes

Reputation: 118681

That's an interesting problem. Your code seems like it should work; you might want to file an enhancement request.

Here's a workaround that seems to work correctly:

class SomeGenericClass<CellType: Cell> {
    func someFunction() {
        let reuseIdentifier = (CellType.self as Reusable.Type).reuseId()
    }
}

Upvotes: 0

Related Questions