目次
概要
iOSアプリ開発経験はあるのですが、
SwiftUIはあまりやったことがなく修行中・・・!
その際「Identifiable」というプロトコルに出くわした際
理解が難しかったので記事にしました。
開発環境
・macOS Sonoma
・Xcode16
・iOS 18
きっかけ
下記のコードを記載した際にとあるエラーが出てきました。
// エラーが出たコード
import SwiftUI
struct User {
let id: Int
let name: String
let age: Int
}
struct ContentView: View {
var users: [User] = []
var body: some View {
VStack {
ForEach(users) { user in // <- ここでコンパイルエラーになる
Text("\(user.name)")
}
}
}
}
そしてコンパイルエラー内容は
Referencing initializer ‘init(_:content:)’ on ‘ForEach’ requires that ‘Book’ conform to ‘Identifiable’
Identifiableが必要な理由
どうやらListやforEachの性質にヒントがあったみたいです。
(ヒントになった記事↓)
https://qiita.com/greeny-ryotaro/items/cf363cdda4e7b99bd39c
https://developer.apple.com/documentation/swift/identifiable
実はforEachのような繰り返し処理の場合、SwiftUIはデータの中身を見ないそうです!!
じゃあどうする?
ではSwiftUIはどのように判別するのでしょうか?
それはデータの中身を見に行くのではなく、
IDなどで識別可能にしておき、
それぞれの要素にアクセスすることが可能となります。
そこで、Identifiableの出番です!
改善後のソースコード
Identifiableプロトコルに準拠させることで解決します。
// IdentifiableでUser構造体のデータを判別させる
struct User:Identifiable {
let id = UUID() // 独自のidを実装
let name: String
let age: Int
}
struct ContentView: View {
var users: [User] = []
var body: some View {
VStack {
ForEach(users) { user in // コンパイルエラーが消える
Text("\(user.name)")
}
}
}
}
Identifiableプロトコルについてもう少し
public protocol Identifiable<ID> {
/// ①
/// A type representing the stable identity of the entity associated with
/// an instance.
associatedtype ID : Hashable
/// ②
/// The stable identity of the entity associated with this instance.
var id: Self.ID { get }
}
①ではIDという名前の関連型を定義しており、
このID型がHashableに準拠している必要があることを意味しています。
②では各インスタンスが一意の識別子を持っていることを保証しています。
やることはシンプルですが、仕組みが少々複雑でしたので
一旦まとめてみました。
コメント