私はあなたの質問に答えることはできると思いますが、あなたが好きな答えではありません。
TL; DR: @objc
関数は現在プロトコル拡張にない場合があります。代わりに基本クラスを作成することもできますが、これは理想的なソリューションではありません。
プロトコル拡張とObjective-C
まず、この質問/回答(Objective-cでアクセスされるプロトコルの拡張で定義されたCan Swiftメソッド)は、プロトコル拡張が内部でディスパッチされる方法が原因で、プロトコル拡張で宣言されたメソッドがobjc_msgSend()
関数から見えないことを示唆しているようです。したがって、Objective-Cコードからは見えません。エクステンションで定義しようとしているメソッドはObjective-Cから見えるようにする必要があるため(それUIKit
を使用できるようにするため)、を含めないことを叫ぶ@objc
が、一度含めると、それはあなたに叫ぶ@objc
は許可されていないプロトコル拡張。これはおそらく、プロトコル拡張機能が現在Objective-Cから見えないためです。
追加するとエラーメッセージが表示されることもわかります @objc
「@ objcは、クラスのメンバー、@ objcプロトコル、およびクラスの具体的な拡張でのみ使用できます」という状態されます。これはクラスではありません。@objcプロトコルへの拡張は、プロトコル定義自体(つまり、要件)にあるものと同じではありません。「具体的」という言葉は、プロトコル拡張が具象クラス拡張としてカウントされないことを示唆しています。
回避策
残念ながら、これにより、デフォルトの実装をObjective-Cフレームワークから認識できるようにする必要がある場合に、プロトコル拡張を使用できなくなります。最初は@objc
、Swiftコンパイラーが準拠する型がクラスであることを保証できないため(具体的に指定した場合でもUIViewController
)、プロトコル拡張では許可されていない可能性があると思いました。したがって、私はにclass
要件を課しましたP1
。これは機能しませんでした。
おそらく、ここでの唯一の回避策は、プロトコルではなく基本クラスを使用することですが、クラスが単一の基本クラスしか持たず、複数のプロトコルに準拠している可能性があるため、これは明らかに完全には理想的ではありません。
この方法を選択する場合は、この質問(サブクラスで呼び出されないSwift 3 ObjCオプションプロトコルメソッド)を考慮してください。Swift 3のもう1つの現在の問題は、サブクラスがスーパークラスのオプションのプロトコル要件の実装を自動的に継承しないことです。その質問への答えは、@objc
それを回避するための特別な適応を使用しています。
問題の報告
私はこれがスウィフトのオープンソースプロジェクトに取り組むものの中に、既に議論されていると思いますが、あなたは彼らが使用していずれかの方法で認識している可能性があり、Appleのバグレポーターそう結局スウィフトコアチームへの道になるだろう、またはスウィフトのバグ報告。ただし、これらのどちらを使用しても、バグが広すぎるか、すでにわかっている場合があります。Swiftチームは、探しているものを新しい言語機能と見なす場合もあります。その場合は、最初にメーリングリストを確認する必要があります。
更新
2016年12月、この問題は Swiftコミュニティに報告されました。この問題は未だ優先度が中のオープンとしてマークされていますが、次のコメントが追加されました。
これは意図されたものです。プロトコルへの準拠後に拡張機能を追加できるため、すべての採用者にメソッドの実装を追加する方法はありません。ただし、拡張機能がプロトコルと同じモジュール内にある場合は、それを許可できると思います。
ただし、プロトコルは拡張機能と同じモジュール内にあるため、Swiftの将来のバージョンでこれを実行できる可能性があります。
アップデート2
2017年2月、この問題は、Swiftコアチームメンバーの1人によって「Wo n't Do」として次のメッセージで正式にクローズされました。
これは意図的なものです。Objective-Cランタイムの制限により、プロトコル拡張では@objcエントリポイントを導入できません。@objcエントリポイントをNSObjectに追加する場合は、NSObjectを拡張します。
拡張しNSObject
たりUIViewController
、あなたが望むものを正確に達成することはできませんが、残念ながらそれは可能になるようには見えません。
(非常に)長期的には、@objc
メソッドへの依存を完全になくすことができるかもしれませんが、Cocoaフレームワークは現在Swiftで記述されていないため(そして、安定したABIになるまでは、そうなることはないため) 。
アップデート3
2019年秋以降、Swiftで記述されるAppleフレームワークが増えているため、この問題の問題は少なくなっています。たとえば、のSwiftUI
代わりにを使用するとUIKit
、メソッド@objc
を参照するときに必要になることはないため、問題を完全に回避できますSwiftUI
。
Swiftで記述されたAppleフレームワークには次のものがあります。
- SwiftUI
- RealityKit
- 組み合わせる
- CryptoKit
Swiftが正式にABIであり、モジュールがSwift 5.0と5.1でそれぞれ安定しているため、このパターンは今後も継続すると予想されます。
@objc