プロトコルが特定のクラスによってのみ採用されることを要求する方法


89

このプロトコルが欲しい:

protocol AddsMoreCommands {
     /* ... */
}

クラスから継承するクラスによってのみ採用されますUIViewControllerこのページは、(構造体ではなく)クラスによってのみ採用されることを指定することで、

protocol AddsMoreCommands: class {
}

しかし、それが特定のクラスによってのみ採用されることを要求する方法を見ることができません。そのページでは、where適合性をチェックするためにプロトコル拡張に句を追加することについて後で説明していますが、それをどのように適応させるかはわかりません。

extension AddsMoreCommands where /* what */ {
}

これを行う方法はありますか?ありがとう!

回答:


114
protocol AddsMoreCommands: class {
    // Code
}

extension AddsMoreCommands where Self: UIViewController {
    // Code
}

4
私はそれをほとんど持っていました... self代わりに私は書きSelfました:-(ありがとう、それはうまく
いき

私にとって、これをキャストと組み合わせて使用​​すると、構文に奇妙な問題が発生します。
クリスプリンス

3
拡張に格納されたプロパティを含めることができないため、プロトコルにプロパティを含める必要がある場合、これは機能しません。
シム

1
これを使用する必要があるプロパティを格納できます:objc_getAssociatedObject(self、&KeyName)as?PropertyTypeは
のMichałZiobro

これには、let / var宣言に型AddsMoreCommandsがあるが、それを渡すメソッドが予期している場合のキャストも必要ですUIViewController
GoatInTheMachine

77

これは拡張なしでも実現できます:

protocol AddsMoreCommands: class where Self: UIViewController {
   // code
}

EDITED 2017/11/04Zigが指摘したように、これはXcode 9.1で警告を生成するようです。現在、Swiftプロジェクトで報告された問題があります(SR-6265)警告を削除います。これを監視し、それに応じて回答を更新します。

EDITED 2018/09/29classインスタンスを格納する変数が弱い必要がある場合(デリゲートなど)に必要です。弱い変数が必要ない場合は、を省略しclassて次のように書くだけで、警告は表示されません。

protocol AddsMoreCommands where Self: UIViewController {
   // code
}

5
私は😲2歳の質問をクリックし、最適なソリューションを1時間前に投稿見つけること、それをどのように偶然です
オスカーApeland

Xcode 9.1は、次のことを警告しています。冗長なレイアウト制約 'Self': 'AnyObject'。レイアウト制約制約 'Self': 'AnyObject'はここに含まれます。私のコードを承認された回答の形式に変更する方が良いようです。
Zig

2
Xcode 9.1以降、クラスのみのプロトコルはのAnyObject代わりに使用するようになりましたclassprotocol AddsMoreCommands: AnyObject where Self: UIViewController { // code }
dodgio 2017年

@dodgioはまだ同じ警告を使用していますAnyObject
rgkobashi 2017年

1
@DávidPásztorは正しいですが、委任などの構造パターンで使用する場合は、プロパティを弱くできるように、「クラス」を明示的に追加する必要があります:)
rgkobashi

48

前の回答の問題のため、私はこの宣言で終わりました:

protocol AddsMoreCommands where Self : UIViewController { 
    // protocol stuff here  
}

Xcode 9.1では警告なし


5
私が間違っている場合は修正してください。ただし、上記の解決策(Xcode 9.1以降で警告が生成されます)に対するこれの問題は、デリゲートを弱いと宣言できないことですか?
カイルゴスラン2018

また、私はスウィフト4.1で、このソリューションを使用する場合、私はのキャストプロパティに必要AddsMoreCommandsUIViewController...私は避けたかった
fl034

8
型キャストを回避するには、この操作を行うことができます:typealias AddsMoreCommandsViewController = UIViewController & AddsMoreCommands
PLU

33

今でスウィフト5次の方法でこれを達成することができます:

protocol AddsMoreCommands: UIViewController {
     /* ... */
}

かなり便利です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.