1. ホーム
  2. swift

Swift のプロトコルエラー: 'weak' は非クラス型に適用できない

2023-08-02 01:07:15

質問

プロトコルとクラスバインドプロトコルの違い、Swiftで使うべきはどちらでしょうか?

protocol A : class { ... }

protocol A { ... }

を追加しようとすると、エラーが発生します。 weak として定義されていない場合に、デリゲートを追加しようとするとエラーが発生します。 : class :

protocol A { ... }

weak var delegate: A

エラーを表示します。

'weak' は非クラス型に適用できません。

または

'weak' はクラスバウンドしない 'A' に適用してはいけません。クラスバウンドするプロトコル適合性を追加することを検討してください。

どのように解決するのですか?

Swift >= 4:

protocol A : AnyObject { ... {

Swift < 4:

protocol A : class { ... }

class-only protocol" : クラス型のみ(構造体や列挙体は不可)がこのプロトコルを採用することができます。

弱参照は 参照型 . クラス は参照型、構造体や列挙型は値型です。 (クロージャも参照型ですが、クロージャはプロトコルを採用できないので、この文脈では関係ありません) プロトコルを採用できないので、この文脈では関係ありません)。

したがって、プロトコルに準拠したオブジェクトを弱いプロパティに格納する必要がある場合、そのプロトコルはクラスのみのプロトコルでなければなりません。

クラス・オンリー・プロトコルを必要とする別の例を示します。

protocol A { 
    var name : String { get set }
}

func foo(a : A) {
    a.name = "bar" // error: cannot assign to property: 'a' is a 'let' constant
}

構造体や列挙型のインスタンスのため、コンパイルされません。 a.name = "bar" の変異であるためです。 a . もし と定義すると、プロトコルは

protocol A : class { 
    var name : String { get set }
}

とすると、コンパイラは a がそのクラス型のインスタンスであることを知る。 a はオブジェクトストレージへの参照です。 そして a.name = "bar" は参照されたオブジェクトを変更しますが a .

一般に、プロトコルを採用する型が値型ではなく参照型である必要がある場合、クラスのみのプロトコルを定義することになります。 プロトコルを採用する型が参照型であり、値型でないことが必要な場合、一般にクラスのみのプロトコルを定義します。