
すいません、別にヤバくはないです。
みなさんはどう書いてますか。
私はこんな感じで書いてました。
final class Card {
  var id: UUID
  var front: String
  var back: String
  init(front: String, back: String) {
    self.id = UUID()
    self.front = front
    self.back = back
  }
}
これを、Apple 公式サンプルではこんなかんじで書いてました。
final class Card {
  var front: String
  var back: String
  init(front: String, back: String) {
    self.front = front
    self.back = back
  }
}
extension Card: Identifiable { }
ID (id) がない!
Playground で見てみます。
final class Card {
  var front: String
  var back: String
  init(front: String, back: String) {
    self.front = front
    self.back = back
  }
}
extension Card: Identifiable { }
let card = Card(front: "前", back: "後")
print(card.id)
print(card.front)
print(card.back)
// ObjectIdentifier(0x0000600000c014d0)
// 前
// 後
id が取れます。
Identifiable を継承しても同様です。
Apple のサンプルコードは少し省略して書きましたが、実際は以下のようなコードです。
final class Card: ObservableObject {
  @Published var front: String
  @Published var back: String
  var creationDate: Date
  init(front: String, back: String, creationDate: Date = .now) {
    self.front = front
    self.back = back
    self.creationDate = creationDate
  }
}
extension Card: Identifiable { }
struct CardCarousel: View {
  @State private var selectedCardID: Card.ID?  // *
  @FocusState private var focusCardID: Card.ID?
  private let initialCardID: Card.ID
  let editing: Bool
  var cards: [Card]
  init(editing: Bool, cards: [Card], selectedCard: Card) {
    self.editing = editing
    self.cards = cards
    initialCardID = selectedCard.id
  }
  var body: some View {
    VStack {
      ScrollView(.horizontal) {
        LazyHStack(spacing: 0) {
         ForEach(cards) { card in // *
           Group {
             if editing {
               CardEditorView(card: card)
             } else {
               FlashCardView(card: card)
                 .id(card.id)
ObjectIdentifier(0x0000600000c014d0) の型は、
Card.ID
です。
また、List 内の ForEach() の引数は一つです。
便利ですよね!
🆔 SwiftData の場合
同じく Apple サンプルコードです。
SwiftData では更に便利になっています。
こちらにもモデルクラスに ID はありません。
Identifiable もありません。
@Model
final class Card {
  var front: String
  var back: String
  var creationDate: Date
  init(front: String, back: String, creationDate: Date = .now) {
    self.front = front
    self.back = back
    self.creationDate = creationDate
  }
}
struct CardCarousel: View {
  @State private var selectedCardID: PersistentIdentifier? // *
  @FocusState private var focusCardID: PersistentIdentifier?
  private let initialCardID: PersistentIdentifier
  let editing: Bool
  var cards: [Card]
  init(editing: Bool, cards: [Card], selectedCard: Card) {
    self.editing = editing
    self.cards = cards
    initialCardID = selectedCard.id
  }
  var body: some View {
    VStack {
      ScrollView(.horizontal) {
        LazyHStack(spacing: 0) {
          ForEach(cards) { card in // *
            Group {
              if editing {
                CardEditorView(card: card)
              } else {
                FlashCardView(card: card)
                  .id(card.id)
ID の型は、PersistentIdentifier です。
書き方は違いますが、同様にモデルクラスにIDなしで使えます。
🆔 まとめ
今回勉強した内容で、以前の Todo アプリを書き換えます。
👉 SwiftUI + SwiftData で ToDo リスト を作ってみる 
少しだけスッキリしました。



