次のクラス階層があります。
_class ScrollableViewController: UIViewController, UITableViewDelegate { // ... }
_
これは、1つのUITableViewDelegate
プロトコルメソッドを実装します。 _tableView:willDisplayCellAt:
_
SpecificScrollableViewController
から継承する私のクラスScrollableViewController
では、新しいオプションのプロトコルメソッドはもう呼び出されません。 tableView(_:heightForRowAt:)
tl; dr関数宣言の前にObjective-C宣言を付ける必要があります。例:.
@objc(tableView:heightForRowAtIndexPath:)
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// return stuff
}
Swift 3 Migration Guide のおかげで、これが解決策であることがわかりました。
適合を宣言するクラスのサブクラスにオプションのObjective-Cプロトコル要件を実装すると、「インスタンスメソッド「…」はプロトコル「…」のオプション要件「…」とほぼ一致します」という警告が表示されます。
•回避策:元のObjective-Cセレクターを内部に使用してオプション要件を実装する前に、
@objc(objectiveC:name:)
属性を追加します。
私はこれがバグであるとかなり確信しています:セレクター機能のチェックを可能にするランタイムダイナミズムがグランドで適切にブリッジされないようですSwiftプロトコルメソッドがサブクラスにあるときの名前の変更。関数宣言の前に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
それを修正するには: https://stackoverflow.com/a/39416386/1109892
@objc(tableView:heightForRowAtIndexPath:)
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// return stuff
}