web-dev-qa-db-ja.com

swift protocolまたはprotocol:classを使用する必要があります

前のVCに情報を送り返すためのプロトコルをセットアップしました。

私はこのように定義しています:

protocol FilterViewControllerDelegate: class  {
    func didSearch(Parameters:[String: String]?)
}

しかし、使用する場合の違いは何ですか:

protocol FilterViewControllerDelegate  {
        func didSearch(Parameters:[String: String]?)
    }

そして、いつ: classプロトコル?

39
user2636197

Swift 4バージョン

AnyObjectは、このようなプロトコル定義に追加されました

protocol FilterViewControllerDelegate: AnyObject  {
    func didSearch(parameters:[String: String]?)
}

クラスのみがそのプロトコルに準拠できることを意味します。

これを考えると

protocol FilterViewControllerDelegate: AnyObject  {
    func didSearch(parameters:[String: String]?)
}

これを書くことができます

class Foo: FilterViewControllerDelegate {
    func didSearch(parameters:[String: String]?) { }
}

しかし[〜#〜] not [〜#〜] this

struct Foo: FilterViewControllerDelegate {
    func didSearch(parameters:[String: String]?) { }
}

Swift 3バージョン

:classこのようなプロトコル定義に追加

protocol FilterViewControllerDelegate: class  {
    func didSearch(Parameters:[String: String]?)
}

クラスのみがそのプロトコルに準拠できることを意味します。

これを考えると

protocol FilterViewControllerDelegate: class  {
    func didSearch(Parameters:[String: String]?)
}

これを書くことができます

class Foo: FilterViewControllerDelegate {
    func didSearch(Parameters:[String: String]?) { }
}

しかし[〜#〜] not [〜#〜] this

struct Foo: FilterViewControllerDelegate {
    func didSearch(Parameters:[String: String]?) { }
}
49
Luca Angeletti

「class」キーワードを使用してプロトコルをマークすることについても、別のことがあります。

それがあなたのプロトコルです:

protocol FilterViewControllerDelegate: class  {
    func didSearch(Parameters:[String: String]?)
}

たとえば、デリゲートプロパティを持つDetailVCを作成していると仮定します。

class DetailViewController: UISomeViewController {
    weak var delegate: FilterViewControllerDelegate
}

「class」キーワードでそのプロトコルをマークしない場合、「デリゲート」プロパティを「弱い」プロパティとしてマークすることもできません。

どうして?

それは簡単です-クラスベースのプロパティのみが弱い関係を持つことができます。参照サイクルを回避しようとしている場合、それが方法です。

20
kokojambo1997

Swift 4.2、Xcode 10の構文:

protocol FilterViewControllerDelegate: AnyObject {
       func didSearch(Parameters:[String: String]?)
}

このプロトコルはクラスのみで採用できます。

最初の質問に答えるために-

しかし、使用する場合の違いは何ですか:

これとの違い:

protocol FilterViewControllerDelegate  {
        func didSearch(Parameters:[String: String]?)
}

このプロトコルは、enumやstructなどの値タイプも採用できるということです。

2番目の質問に答えるため-

そして、いつクラスプロトカルを使用すべきですか?

クラスプロトコルを使用する必要がある場合、デリゲートパターンの次の例を説明します。デリゲートプロトコルがあることを想像してください。

protocol PopupDelegate: AnyObject {
    func popupValueSelected(value: String)
}

別のクラスでプロパティを作成します

var delegate: PopupDelegate?

しかし、これにはメモリリークの問題につながる可能性のある強力なリファレンスがあります。メモリリークを修正する1つの方法は、デリゲートプロパティを作成することです-弱いです。プロトコルをクラスにのみ適用できるようにするまで、Swiftはプロトコルを値型にも適用できると考えています。

weak var delegate: PopupDelegate?

デリゲートをweakのように宣言しようとすると、次のエラーが表示されます。

「弱い」変数は、「PopupDelegate」ではなく、クラスおよびクラスにバインドされたプロトコルタイプにのみ適用されます

しかし、値型にウィークを適用することはできません。そのため、プロトコルを参照型に制限する必要があります。そのためSwiftはその参照型であることを認識しています。このデリゲートを弱いと宣言できるようにするには、使用するプロトコルを制限する必要がありますクラスのみ:

protocol PopupDelegate: AnyObject {
    func popupValueSelected(value: String)
}
7
swift2geek

定義するプロトコルは、構造体または列挙型ではなく、クラスでのみ採用できることを意味します。

から 公式Swift book

protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
    // class-only protocol definition goes here } 

上記の例では、SomeClassOnlyProtocolはクラスタイプでのみ採用できます。 SomeClassOnlyProtocolを採用しようとする構造または列挙定義を記述することは、コンパイル時エラーです。

5
alexburtnik

Swift 3.2アップデート:

クラスのみのプロトコルを宣言するには、次のように記述します。

protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
    // class-only protocol definition goes here
}

の代わりに

protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
    // class-only protocol definition goes here
}

2番目のスニペットは今のところまだ機能しているようです。リファレンス: https://developer.Apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html

1
J.beenie