Swift Generics и расширения протокола

У меня есть протокол Reusable, который имеет статическую функцию static func reuseId() -> String и расширение протокола, определяющее реализацию функции по умолчанию. Затем я реализовал расширение для UITableViewCell, чтобы оно соответствовало протоколу Reusable. Теперь я могу без проблем использовать эту функцию в своих TableViewCells: SomeTableViewCell.reuseId().

У меня проблема с дженериками. У меня есть универсальный класс с общим параметром типа UITableViewCell:

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

Я хочу иметь возможность использовать функцию, указанную в Reusable, в моем универсальном классе на CellType, но, к сожалению, это не работает должным образом. Компилятор всегда выдает ошибку Type 'CellType' has no member 'reuseId'.

Кто-нибудь знает, почему это происходит? Есть ли обходной путь?

Я использую Xcode 7.0 со Swift 2.0.

Привет из Германии

ОБНОВЛЕНИЕ: вот пример кода, который лучше показывает мою проблему:

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()
    }
}

Этот код будет генерировать указанную выше ошибку, но я не совсем понимаю, почему это происходит. Я думаю, что основное отличие от примера кода, опубликованного jtbandes, заключается в том, что я использую статическую функцию.


ОБНОВЛЕНИЕ: проблема устранена в Xcode 8.3 beta 2. Приведенный выше пример кода теперь работает должным образом (конечно, после его переноса на Swift 3).


person naglerrr    schedule 20.09.2015    source источник
comment
Было бы полезнее, если бы вы разместили (минимальный) пример фактического кода, а не только описывали проблему.   -  person Martin R    schedule 20.09.2015
comment
Я добавил пример кода к своему исходному вопросу, который, надеюсь, сделает мой вопрос более понятным.   -  person naglerrr    schedule 20.09.2015


Ответы (2)


Это интересная проблема. Похоже, ваш код должен работать; вы можете отправить запрос на улучшение.

Вот обходной путь, который работает правильно:

class SomeGenericClass<CellType: Cell> {
    func someFunction() {
        let reuseIdentifier = (CellType.self as Reusable.Type).reuseId()
    }
}
person jtbandes    schedule 20.09.2015
comment
Но CellType наследуется от UITableViewCell, который уже соответствует Reusable. Мне кажется, что нужно больше информации, я не смог воспроизвести проблему на простом примере. - person Martin R; 20.09.2015
comment
Спасибо @MartinR, наверное, я неправильно понял вопрос. Да, нужно больше информации... - person jtbandes; 20.09.2015
comment
Спасибо. Я опубликовал радар 22776964. Ваш обходной путь пока работает нормально, поэтому я отмечу ваш ответ как правильный. Я обновлю вопрос, как только Apple ответит на радар. - person naglerrr; 21.09.2015

Другой (обходной) способ получить то, что вам нужно:

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

GenericExample<UITableViewCell>().test() // returns "UITableViewCell"
GenericExample<MyCell>().test() // returns "MyCell"
person Benzi    schedule 21.09.2015
comment
PS Исходный сценарий, скорее всего, является ошибкой, поскольку модель автозаполнения в XCode знает, что CellType имеет resuseID(), но компилятор жалуется иначе - person Benzi; 21.09.2015