2016-09-09 4 views
14

у меня есть следующие иерархии классов:Swift 3 ObjC Дополнительный протокол Метод не вызывается в подклассе

class ScrollableViewController: UIViewController, UITableViewDelegate { // ... } 

, который реализует один метод UITableViewDelegate протокола, например tableView:willDisplayCellAt:

В моем классе SpecificScrollableViewController, который наследуется от ScrollableViewController, новые необязательные методы протокола больше не вызываются, например. tableView(_:heightForRowAt:)

ответ

29

tl; dr необходимо префикс объявления функции с помощью объявления Objective-C, например.

@objc(tableView:heightForRowAtIndexPath:) 
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 
    // return stuff 
} 

Я был предупрежден к этому являющемуся решению благодаря Swift 3 Migration Guide, которая гласит:

Если вы реализуете факультативное требование протокола в Objective-C в подклассе класса, который декларирует соответствие, вам 'см. предупреждение: «Метод экземпляра« ... »почти соответствует необязательному требованию« ... »протокола« ... »«

• Обход проблемы: добавьте атрибут @objc(objectiveC:name:) перед выполнением необязательного требования с оригинальной Ob селектор jective-C внутри.

Я абсолютно уверен, что это ошибка: оказывается, что среда выполнения динамизм, что позволяет проверять возможности селектора не получает правильно мостик в Большом Swift переименовании, когда метод протокола в подклассе. Префикс объявления функции с именем Objective-C должным образом переводит Swift в Objective-C и позволяет запрашивать Swift 3 переименованные методы с помощью canPerformAction:withSender: из Objective-C

+0

О, господа, это сработало для меня спасибо! Трудно так тонко. – cgossain

+1

@cgossain мое удовольствие! Я боролся с этим в течение 6 часов, прежде чем нашел его :( –

+0

вы также можете использовать private перед функцией, чтобы отключить предупреждение – rashfmnb

2

Это, как представляется, исправлено в Swift 3.0.1 для нормального подклассы, но не является фиксированной для общих подклассов:

class A: NSObject, UITableViewDelegate {} 

class B: A { 
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {} 
} 

class C<T>: A { 
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {} 
} 

print(#selector(B.tableView(_:didSelectRowAt:))) // tableView:didSelectRowAtIndexPath: 
print(#selector(C<Int>.tableView(_:didSelectRowAt:))) // tableView:didSelectRowAt: 

См: https://bugs.swift.org/browse/SR-2817

Чтобы это исправить: https://stackoverflow.com/a/39416386/1109892

@objc(tableView:heightForRowAtIndexPath:) 
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 
    // return stuff 
} 
Смежные вопросы