[Swift] protocol Identifiable をよく理解する

Swift

SwiftUI でもよく使う protocol の1つ Identifiable をあらためて説明してみます。

環境&対象

以下の環境で動作確認を行なっています。

  • macOS Monterery beta 5
  • Xcode 13 beta5
  • iOS 15 beta

protocol Identifiable

Identifiable protocol に準拠させることができるものは、class と struct, enum のいずれも準拠できます。

MEMO
技術的には、enum を Identifiable に準拠させて実装することもできますが、enum の意味から考えると 無意味な実装となることが多いと思われます。

Identifiable に準拠させることで、要素に ID を振っていることを明示します。

この ID を使うことで、オブジェクトが同一であることや違うことの判断ができることが期待されます。

ID には、以下のいずれかの特徴を期待できます。

  • 常にユニークである
  • コンテキストごとに永久的にユニークである
  • プロセス内でユニークである
  • オブジェクトが存在する間 ユニークである
  • 集合(コレクション)内で ユニークである

どの範囲で、どの程度ユニークかは、使用する側が要求しますが、実際にどの程度ユニークかは実装に依存します。

UUID を使っているならば、常にユニークと考えることができますが、Array の中の要素のインデックスを ID として使用するならば、集合の中でのみユニークさが保証されることになります。

Identifiable のデフォルト実装(class 向け)

class に Identifiable を指定すると、 デフォルト実装として ObjectIdentifier を使用したものが提供されます。

Apple のドキュメントは、こちら

この実装は、インスタンスが存在する範囲でのみユニーク性が保証されています。

Identifiable に conform するということ

var id

var id というプロパティが必要となります。

ですので、MyStruct という struct を Identifiable に conform させるならば、以下のような実装になります。


struct myStruct: Identifiable {
  // (1)    
  var id: UUID = UUID()
}
コード解説
  1. var id を定義しています。さらに、デフォルト値として UUID() を設定しているため、常にユニークな id を設定していることになります

associatedtype ID

見落としがちですが、associatedtype も定義されます。

以下のようにすると、ID が定義されていることが確認できます。


struct MyStruct: Identifiable {
    var id: UUID = UUID()
}

let check = type(of: MyStruct.ID.self)
print(check)
// print-out
UUID.Type

MyStruct.ID の型は、UUID となります。(コードからもわかりますが・・)

Generics や associatedtype を使った実装で Identifiable を期待しているケースでは、この ID を使って記述していくことになります。

Identifiable protocol まとめ
  • id というプロパティを定義する必要がある
  • id の型は、associatedtype ID として定義される
  • Identifiable の id がどの程度ユニークであるかは、規定がなく、実装側/使用側で合意できていれば実装に制約はない
  • class を Identifiable に準拠させると デフォルト実装も提供される(ただし、インスタンスが存在する範囲でのみユニーク)
  • Generics や associatedtype を使った実装を行う場合で、Identifiable を期待するケースでは、associatedtype ID を使用して実装することになる

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です