LoginSignup
47
19

More than 3 years have passed since last update.

[Swift] Class-only Protocolは": class"じゃなくて": AnyObject"で宣言することに慣れましょう

Last updated at Posted at 2020-03-22

概要

本記事の前提環境:Swift 5.1

ちょっと今さら感があるネタですが。。。

Class-only Protocolは、
↓こうじゃなくて

protocol MyDelegate: class {
}

↓こう宣言しましょう、という話題です。

protocol MyDelegate: AnyObject {
}

私なりに知ってはいたのですがメンバーに理由をうまく説明できなかったので、今さらながら整理してみました。

前置き

Xcodeでこのような実装をするとエラーになるので、こういう実装はできないのだな、ということにすぐに気づくと思います。

protocol MyDelegate {
}

class MyClass {
  weak var delegate: MyDelegate?
}

weakは循環参照を避けるために「弱参照にします」というキーワードであって、参照型の変数じゃないと意味がないため、MyDelegateを参照型だけに適用できるような宣言をしないとダメですよ、という訳です。

本題

Swift 3までは、このような↓書き方をしていました。

protocol MyDelegate: class {
}

Swift 4で、SE-0156という提案に基づいて、AnyObjectが導入されました。
以降は、こちら↓の書き方が推奨となっています。

protocol MyDelegate: AnyObject {
}

参考:Swift Documentation – Class-only Protocols

SE-0156の背景と意図は私には完璧に読み取り難いですが、AnyObjectとは「参照型全般」という意味を明確にしたモノ、という理解です。

参考:SwiftのAnyObjectとAnyについて

Swift 4以降、classは後方互換のためにAnyObjectのtypealias(別名)として残っている状態です。

結論

Swift 5.1現在では、: classで宣言してもエラーになりませんし警告も出ません。
また、ビルドや実行時に遅くなるということもないようです。

ただし、SE-0156には以下のような記述もあり、将来はdeprecatedとして警告が発生する可能性があります。

Later, class could be removed in a subsequent version of Swift.

このため、コードに: classを見かけたら、: AnyObjectにリファクタリングしておいた方が良さそうです。

47
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
19