Необязательный метод протокола Swift 3 ObjC в подклассе
У меня есть следующая иерархия классов:
class ScrollableViewController: UIViewController, UITableViewDelegate { // ... }
Это реализует один UITableViewDelegate
метод протокола, например tableView:willDisplayCellAt:
В моем классе SpecificScrollableViewController
, который наследует от ScrollableViewController
новые дополнительные методы протокола больше не вызываются, например tableView(_:heightForRowAt:)
2 ответа
tl;dr вам нужно добавить префикс объявления функции к объявлению Objective-C, например
@objc(tableView:heightForRowAtIndexPath:)
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// return stuff
}
Я был предупрежден о том, что это решение, благодаря Руководству по миграции Swift 3, в котором говорится:
Если вы реализуете необязательное требование протокола Objective C в подклассе класса, который объявляет соответствие, вы увидите предупреждение: "Метод экземпляра"… "почти соответствует необязательному требованию"… "протокола"… ".
• Обходной путь: добавьте
@objc(objectiveC:name:)
атрибут перед реализацией необязательного требования с оригинальным селектором Objective-C внутри.
Я вполне уверен, что это ошибка: кажется, что динамизм во время выполнения, который позволяет проверять возможности селектора, не соединяется должным образом в Grand Swift Renaming, когда метод протокола находится в подклассе. Префикс объявления функции с именем Objective-C правильно соединяет Swift с Objective-C и позволяет запрашивать переименованные методы Swift 3 с помощью canPerformAction:withSender:
изнутри Objective-C
Кажется, это исправлено в 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
Чтобы это исправить: /questions/17433804/neobyazatelnyij-metod-protokola-swift-3-objc-v-podklasse/17433808#17433808
@objc(tableView:heightForRowAtIndexPath:)
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// return stuff
}