りんご192546 views
いろは2986023 views
高校倫理1433119 views
高校生物549842 views
小学理科717236 views
中学英語808712 views
教育148875 views
中学理科1626207 views
中学社会667106 views
LaTeX957300 views
Help
Tools

English

Identifiable プロトコルと id 指定

SwiftUI の List や ForEach でデータを表示する際、各要素を一意に識別するための仕組みが必要です。Identifiable プロトコルと id パラメータについて解説します。

なぜ識別子が必要なのか

SwiftUI はリストの各要素を追跡し、データが変更されたときに効率的に UI を更新します。この追跡には一意の識別子が必要です。識別子がないと、要素の追加・削除・並び替え時に正しくアニメーションできなかったり、パフォーマンスが低下したりします。

id パラメータによる識別

最もシンプルな方法は、ForEach や List に id パラメータを渡すことです。

struct ContentView: View {
    let fruits = ["りんご", "みかん", "バナナ"]
    
    var body: some View {
        List(fruits, id: \.self) { fruit in
            Text(fruit)
        }
    }
}

id: \.self は要素そのものを識別子として使うことを意味します。String や Int など Hashable に準拠した型で使えますが、重複する値があると問題が発生します。

// 危険な例:重複する値がある
let items = ["A", "B", "A", "C"]  // "A" が重複

List(items, id: \.self) { item in
    Text(item)
}

重複があると SwiftUI は同じ要素として扱ってしまい、意図しない動作の原因になります。

Identifiable プロトコル

カスタム型を使う場合は、Identifiable プロトコルに準拠させるのがベストプラクティスです。

struct Task: Identifiable {
    let id = UUID()
    var title: String
    var isCompleted: Bool
}

Identifiable に準拠するには、id プロパティを実装するだけです。UUID を使えば自動的に一意の値が生成されます。

struct TaskListView: View {
    let tasks = [
        Task(title: "買い物", isCompleted: false),
        Task(title: "掃除", isCompleted: true),
        Task(title: "洗濯", isCompleted: false)
    ]
    
    var body: some View {
        List(tasks) { task in
            HStack {
                Text(task.title)
                Spacer()
                if task.isCompleted {
                    Image(systemName: "checkmark")
                }
            }
        }
    }
}

Identifiable に準拠した型を使う場合、id: パラメータは省略できます。

既存のプロパティを id として使う

データベースから取得したデータなど、すでに一意の ID を持っている場合は、それを使うこともできます。

struct User: Identifiable {
    let id: Int  // データベースの主キー
    var name: String
    var email: String
}
UUID を使う場合

新規に作成するデータで、永続化の必要がない場合に便利。自動的に一意な値が生成される。

既存の ID を使う場合

データベースや API から取得したデータで、すでに一意の ID が割り当てられている場合に使用。

id にキーパスを指定

Identifiable に準拠していない型でも、id パラメータにキーパスを指定すれば使えます。

struct Item {
    let code: String
    var name: String
}

struct ContentView: View {
    let items = [
        Item(code: "001", name: "商品A"),
        Item(code: "002", name: "商品B"),
        Item(code: "003", name: "商品C")
    ]
    
    var body: some View {
        List(items, id: \.code) { item in
            Text(item.name)
        }
    }
}

id: \.code で code プロパティを識別子として使用しています。ただし、可能であれば Identifiable プロトコルに準拠させる方が Swift らしい書き方です。