Swift 3 ObjC Необязательный метод протокола, не вызываемый в подклассе
У меня есть следующая иерархия классов:
class ScrollableViewController: UIViewController, UITableViewDelegate { // ... }
Это реализует один метод протокола UITableViewDelegate
, например. tableView:willDisplayCellAt:
В моем классе SpecificScrollableViewController
, который наследуется от ScrollableViewController
, новые необязательные методы протокола больше не вызываются, например. tableView(_:heightForRowAt:)
Ответы
Ответ 1
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:)
перед реализацией необязательного требования с помощью селектора Objective-C внутри.
Я уверен, что это ошибка: похоже, что динамический динамик, который позволяет проверять возможности выбора, не получает должным образом моста в переименовании Grand Swift, когда метод протокола находится в подклассе. Префикс объявления функции с именем Objective-C правильно переводит Swift на Objective-C и позволяет запрашивать Swift 3 переименованные методы с помощью canPerformAction:withSender:
из Objective-C
Ответ 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
Чтобы исправить это: fooobar.com/info/108971/...
@objc(tableView:heightForRowAtIndexPath:)
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// return stuff
}