Подтвердить что ты не робот

Swift 3 ObjC Необязательный метод протокола, не вызываемый в подклассе

У меня есть следующая иерархия классов:

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

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

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

4b9b3361

Ответ 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
}