概要
本記事の前提環境: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 4以降、class
は後方互換のためにAnyObject
のtypealias(別名)として残っている状態です。
結論
Swift 5.1現在では、: class
で宣言してもエラーになりませんし警告も出ません。
また、ビルドや実行時に遅くなるということもないようです。
ただし、SE-0156には以下のような記述もあり、将来はdeprecatedとして警告が発生する可能性があります。
Later,
class
could be removed in a subsequent version of Swift.
このため、コードに: class
を見かけたら、: AnyObject
にリファクタリングしておいた方が良さそうです。