[解決済み] 非'@objc'メソッドは'@objc'プロトコルのオプション要件を満たしていない
質問
概要
- Objective-Cのオプション関数の1つのデフォルトの実装を提供するプロトコルP1を持っています。
- オプション関数のデフォルトの実装を提供するとき、警告が表示されます。
コンパイラの警告です。
Non-'@objc' method 'presentationController(_:viewControllerForAdaptivePresentationStyle:)' does not satisfy optional requirement of '@objc' protocol 'UIAdaptivePresentationControllerDelegate'
バージョン
- スウィフト:3
- Xcode。8 (パブリック リリース)
試行回数です。
-
追加しようとしたもの
@objc
を追加してみましたが、役に立ちません。
質問です。
- これを解決するにはどうしたらよいですか?
- 回避策はありますか?
コードです。
@objc protocol P1 : UIAdaptivePresentationControllerDelegate {
}
extension P1 where Self : UIViewController {
func presentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
return UIViewController()
}
}
class A : UIViewController, P1 {
}
どのように解決するのですか?
あなたの質問に答えることができると思いますが、あなたが気に入るような答えではありません。
TL;DRです。
@objc
関数は現在プロトコル拡張に含まれていないかもしれません。代わりに基底クラスを作成することもできますが、それは理想的な解決策ではありません。
プロトコル拡張と Objective-C
まず、この質問/回答(
Objective-cでアクセスされるプロトコル上の拡張機能で定義されたSwiftメソッドは可能か?
) は、プロトコル拡張がフードの下でディスパッチされる方法のために、プロトコル拡張で宣言されたメソッドが
objc_msgSend()
関数には表示されず、したがって Objective-C コードからは見えません。拡張機能で定義しようとしているメソッドは Objective-C から見える必要があるので (つまり
UIKit
が使用できるように) Objective-C から見える必要があるため、拡張機能で定義しようとしているメソッドに
@objc
を含まないことに対して怒鳴りますが、 含めた後は
@objc
はプロトコル拡張では許可されないからです。これはおそらく、プロトコル拡張は現在 Objective-C からは見ることができないからでしょう。
また、一度エラーメッセージに
@objc
は "@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes." これはクラスではありません。@objc プロトコルの拡張はプロトコル定義自体(つまり要件)にあるのと同じではなく、また "concrete" という言葉はプロトコル拡張が具象クラス拡張としてカウントされないことを示していると思われます。
回避策
残念ながら、デフォルトの実装が Objective-C フレームワークから見える必要がある場合、これはプロトコル拡張の使用をかなり完全に妨げます。最初、私はおそらく
@objc
がプロトコル拡張子で許可されていないのは、Swift コンパイラが適合する型がクラスであることを保証できないからではないかと考えました (たとえあなたが具体的に
UIViewController
). そこで、私は
class
の要件を
P1
. これはうまくいきませんでした。
おそらく唯一の回避策は、ここでプロトコルの代わりに単純にベースクラスを使用することですが、クラスが単一のベースクラスしか持っていなくても複数のプロトコルに適合することがあるため、これは明らかに完全に理想的なものではありません。
このルートを選択した場合、この質問(
Swift 3 ObjC オプションのプロトコルメソッドがサブクラスで呼び出されない
) を考慮してください。Swift 3 の別の現在の問題は、サブクラスが自動的にそれらのスーパークラスのオプションのプロトコル要件の実装を継承しないことであると思われます。その質問に対する答えは、特別に適応された
@objc
の特別な適応を使用して、それを回避します。
問題を報告する
この件は、Swift のオープンソースプロジェクトで作業している人たちの間ですでに議論されていると思いますが、彼らが認識していることを確認するために Apple のバグ リポーター を使用するか、最終的に Swift コア チームに届くと思われる Swift のバグ報告者 . これらのいずれかが、あなたのバグが広すぎるか、すでに知られていることを見つけるかもしれません。Swift チームは、あなたが探しているものが新しい言語機能であるとみなすかもしれません。 メーリングリスト .
更新情報
2016年12月に、この問題 が報告されました をSwiftコミュニティに提出しました。この問題はまだ優先度「中」でオープンとなっていますが、以下のコメントが追加されています。
これは意図的なものです。拡張はプロトコルへの適合後に追加される可能性があるので、すべての採用者にメソッドの実装を追加する方法はありません。拡張機能がプロトコルと同じモジュールにあれば許可できるのでしょうけど。
プロトコルが拡張機能と同じモジュールにあるので、しかし、Swiftの将来のバージョンでこれを行うことができるかもしれません。
アップデート2
2017年2月、この問題 は正式に終了しました as "Won't Do"として、Swift Core Teamのメンバーの一人が次のようなメッセージを残しています。
これは意図的なものです。Objective-C ランタイムの制限により、プロトコル拡張は @objc エントリポイントを導入することができません。NSObject に @objc エントリ ポイントを追加したい場合は、NSObject を拡張してください。
拡張する
NSObject
あるいは
UIViewController
は、まさにあなたが望むものを達成することはできませんが、残念ながら可能になるとは思えません。
(非常に) 長期的な将来では、私たちは
@objc
メソッドへの依存を完全になくすことができるかもしれませんが、Cocoa フレームワークは現在 Swift で書かれていないため (そして Swift が安定した ABI を持つまでそうできない)、その時はおそらくすぐには来ないでしょう。
アップデート 3
2019年秋現在、AppleのフレームワークがSwiftで書かれることが多くなってきているため、この問題は少なくなってきています。例えば
SwiftUI
の代わりに
UIKit
を使用すると、問題を完全に回避できます。
@objc
は決して必要ないからです。
SwiftUI
メソッドを参照するときには決して必要ありません。
Swiftで書かれたAppleのフレームワークには
- SwiftUI
- リアリティキット
- 組み合わせる
- 暗号化キット
Swift が Swift 5.0 と 5.1 の時点でそれぞれ公式に ABI とモジュールが安定しているので、このパターンは時間とともに継続すると予想されます。
関連
-
swift 4.0でのdispatch_async,dispatch_afterの使用について
-
[解決済み] 純粋な」Swift で弱いプロトコル参照を作るには (@objc なしで) どうしたらいいですか?
-
[解決済み] Swiftのプロトコルでオプションのメソッドを定義するには?
-
[解決済み] Swiftで1つのビューコントローラの向きを縦向きのみに固定する方法
-
[解決済み] Protocol ... can only be used as generic constraint because it has Self or associated type requirements "とは、どういう意味ですか?
-
[解決済み] Swift 3でカスタム通知を作成するには?
-
[解決済み] Swiftで複数のカスタムセルを持つUITableview
-
[解決済み] ""内の二重引用符を印刷するには?
-
[解決済み] Swift: PREPROCESSORフラグ(`#if DEBUG`など)を使ってAPIキーを実装する方法とは?
-
[解決済み] Swift: インデックスで文字列配列を置換する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Swift の Optional 値 && Optional のアンラップ時に予期せず nil が検出された場合の説明
-
swift 4.0でのdispatch_async,dispatch_afterの使用について
-
[解決済み] Swiftで1つのビューコントローラの向きを縦向きのみに固定する方法
-
[解決済み] Swiftダブルからストリング
-
[解決済み] Protocol ... can only be used as generic constraint because it has Self or associated type requirements "とは、どういう意味ですか?
-
[解決済み] swiftで改行なしの印刷をする
-
[解決済み] Swift 1.2では、宣言は「final」と「dynamic」の両方にはなり得ないというエラーがある
-
[解決済み] Swiftで警告を消すには?
-
[解決済み] Swiftで複数のカスタムセルを持つUITableview
-
[解決済み] Swift - 複数条件でオブジェクトの配列を並べ替える