SwiftUI でアプリを作ると、必ずと言っていいほど登場する Identifiable。今回は、なぜモデルに Identifiable を付けるのか、SwiftUI が内部で何をしているのか、実務経験が浅くても理解できるよう丁寧に解説します。
Identifiable とは?
Identifiable は「そのデータが何者かを一意に示す ID を持っていること」を表すプロトコルです。
SwiftUI の List や ForEach は、データを並べて表示するときに、「どのデータがどのセルなのか?」を判断する必要があります。
そのときに使われるのが id です。
Identifiable に準拠するには、実は必要な条件はたった 1つだけです。
- 一意の id を持っていること
例えば SNS の投稿 Post モデルでは、次のように id を持たせます。
struct Post: Identifiable {
let id: String // ← これだけで Identifiable になる
let text: String
}この id を SwiftUI が使って、表示の更新時に「同じ投稿かどうか」を判断します。以下のように、Post が Identifiable に準拠している場合、List はとてもシンプルに書けます。
// Post が Identifiable 準拠の場合
struct Post: Identifiable {
let id: String
let text: String
}
List(posts) { post in
Text(post.text)
}一方、Post が Identifiable に準拠していない場合は、List に「どのプロパティを ID として使うか」を毎回教えてあげる必要があります。
// Identifiable に準拠していない場合
struct Post {
let id: String
let text: String
}
// List 側で「id を識別子にして」と明示する必要がある
List(posts, id: \.id) { post in
Text(post.text)
}どちらも動きますが、モデル側を Identifiable にしておくと。
List/ForEachの呼び出しが毎回スッキリする- 「この型は必ず一意なIDを持っている」という前提がコード上で明示できる
- タイムラインなど別の画面でも、そのまま再利用しやすい
そのため、投稿やユーザーなど「ID を持つことが前提のモデル」は、最初から Identifiable に準拠させておくのがおすすめです。
Identifiable に準拠していないデータの場合、List に渡すときに id: を指定しなければいけませんが、Identifiable を実装していれば余計な指定は不要です。
つまり Identifiable は、SwiftUI の List / ForEach を「自然に使える状態」にするための “身分証明書” のようなものです。
なぜSwiftUIでIdentifiableが重要なのか?
SwiftUI の List や ForEach は、「どのデータがどの行に対応しているか」を常に追跡しています。データの更新時には、id を元に差分を計算し、必要な部分だけを再描画します。
例えば:
List(posts) { post in
Text(post.text)
}このとき SwiftUI は、posts 配列内の各 post が “どのセルか” を識別するために post.id を使用します。
もし id がなければどうなるか?
- 行のどれが削除されたのか判断できない
- どれが更新されたのか判別できない
- すべてのセルが作り直されてスクロール位置が飛ぶ
- アニメーションが不自然になる
つまり、Identifiable はSwiftUIの差分更新の基盤です。
Identifiable を使う具体例
私の開発しているアプリ「朝の実」で使っている Post モデルは以下のようになっています。
struct Post: Identifiable {
let id: String // ここがID
let authorId: String
let text: String
let createdAt: Date
var cheerCount: Int
var isDeleted: Bool
let clientTimeZone: String
}ID に何を使うべき?
SwiftUI やデータモデル設計では、「そのデータを一意に識別できる ID」をどう設計するかがとても重要です。以下に、一般的に推奨される ID の選び方をまとめます。
① 永続的に変わらない ID を使う(UUID / データベースIDなど)
アプリを再起動しても変わらない ID を使うのが最も安全です。
例えば、投稿・ユーザー・コメントなどは、毎回同じ ID を参照できる必要があります。
よく使われるのは:
- UUID(
UUID().uuidString) - バックエンド側のユニーク ID(データベースが生成したもの)
これらは「一意性が保証された値」であり、競合や重複が起こらないため、ID に最適です。
また、Swift では UUID を以下のように生成します。
let id = UUID().uuidStringUUID は衝突する可能性が極めて低く、ほぼ確実に一意な ID として利用できます。
② index(配列の順番)を ID にしてはいけない
配列の添字(0, 1, 2…)を ID として使うのは絶対に避けるべきです。
- 並び順が変わった瞬間に ID が変わる
- データを削除すると、後ろの全要素の ID が変わる
- SwiftUI の差分計算が正しく動かなくなる
「不安定な ID」は SwiftUI の描画バグや、リスト更新時のクラッシュにつながります。
要するに ID は “変わらない一意な値” を使う
アプリのモデルが扱う ID は、次の条件を満たしていることが重要です:
- 一意である(他と重複しない)
- 永続的である(並び順や操作で変化しない)
Post、User、Comment など「実体を識別するデータ」は、UUID を ID にしておくのが最も安全で実務でも一般的です。
まとめ
- Identifiable = 個体識別のためのプロトコル
idを使って SwiftUI が差分更新(Diffing)する- List / ForEach / アニメーションで必須の存在
SwiftUI を使ううえで Identifiable の理解は避けて通れません。 今回の記事が、モデル設計や UI 更新の仕組みを理解する一助になれば幸いです。
