SwiftDataでネストした子ModelのArrayは順番がぐちゃぐちゃになる。

# 検証
<details><summary>検証用コード</summary>
（SwiftDataを有効化したプロジェクトの初期コードにちょっと追加。差分はおおよその目安）

```App.swift
import SwiftUI
import SwiftData

@main
struct testSwiftDataApp: App {
    var sharedModelContainer: ModelContainer = {
        let schema = Schema([
            Item.self,
        ])
        let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)

        do {
            return try ModelContainer(for: schema, configurations: [modelConfiguration])
        } catch {
            fatalError("Could not create ModelContainer: \(error)")
        }
    }()

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(sharedModelContainer)
    }
}
```

```diff_swift
import SwiftUI
import SwiftData

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var items: [Item]

    var body: some View {
        NavigationSplitView {
            List {
                ForEach(items) { item in
                    NavigationLink {
                        Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))")
+                       ForEach(item.notes) { note in
+                           Text(note.value)
+                       }
                    } label: {
                        Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
                    }
                }
                .onDelete(perform: deleteItems)
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    EditButton()
                }
                ToolbarItem {
                    Button(action: addItem) {
                        Label("Add Item", systemImage: "plus")
                    }
                }
            }
        } detail: {
            Text("Select an item")
        }
    }

    private func addItem() {
        withAnimation {
            let newItem = Item(
                timestamp: Date(),
+                notes: [
+                    Note(value: "A"),
+                    Note(value: "B"),
+                    Note(value: "C"),
+                ]
            )
            modelContext.insert(newItem)
        }
    }

    private func deleteItems(offsets: IndexSet) {
        withAnimation {
            for index in offsets {
                modelContext.delete(items[index])
            }
        }
    }
}
```

```diff_swift
import Foundation
import SwiftData

@Model
final class Item {
    var timestamp: Date
+    var notes: [Note]

    init(timestamp: Date, notes: [Note]) {
        self.timestamp = timestamp
+        self.notes = notes
    }
}

+ @Model
+ final class Note {
+     var value: String
+ 
+     init(value: String) {
+         self.value = value
+     }
+ }
```
</details>

# 検証結果

|List|Detail 0|Detail 1|Detail 2|
|-|-|-|-|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/c3b18517-df03-1cee-0c68-541f264e86f3.png)|![Simulator Screenshot - iPhone 15 - 2024-02-19 at 12.55.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/f0f06a62-c936-4922-7dcb-da8fc0c506da.png)|![Simulator Screenshot - iPhone 15 - 2024-02-19 at 12.55.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/e64f6e2c-26d0-5a21-206a-36caafa255d4.png)|![Simulator Screenshot - iPhone 15 - 2024-02-19 at 12.55.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/75300e91-76c5-27c1-8d2e-e091aae358d0.png)|

### 順番ぐちゃぐちゃやないかい！
:::note info
仮説：SwiftDataにおいて`[子Model]`の配列は順番がぐちゃぐちゃになる?
:::

<details><summary>証跡</summary>


```
        .onAppear {
            for item in items {
                print(item._notes.map {$0.value})
            }
        }
        
```
として表示してみると
```
["A", "C", "B"]
["A", "B", "C"]
["B", "C", "A"]
["A", "C", "B"]
["C", "A", "B"]
["A", "C", "B"]
["A", "B", "C"]
["B", "A", "C"]
["C", "B", "A"]
...
```
となった。 確かにぐちゃぐちゃ。
</details>

# 対策

#### A. 子ModelをModelじゃなくする。
そもそも上記コードにおいて、`Note`に`@Model`を適用し`PersistentModel`に準拠させる必要がない。
なので、以下のように変更する。

```Note.swift
struct Note { // Swiftの値型中心の思想に従い、不可欠でなければclassではなくstructを選ぶ。
    var value: String
    let id: UUID
    init(value: String) {
        self.value = value
        self.id = UUID()
    }
}

extension Note: Identifiable {} // ForEachで回すために準拠必要。

extension Note: Codable {} // SwiftDataで独自型を永続化するには、その型はCodableである必要がある。 
```

その他コードは変更なし。
Codableに関しては[こちらの記事](https://qiita.com/hayason00/items/3d83078f1fd630f65b85)が参考になる

#### B. 回り道(Work Around)をする。
子Modelの配列および配列の順番が必要な場合、以下のようにすると意図した通りに動作した。

```swift
@Model
final class Item {
    var timestamp: Date
    private var _notes: [Note] // [Note]を保持する。
    private var idsInOrder: [UUID] // 順番をidで保持する。
    // [some PersistantModel]でない普通の配列の順番は保証される（仮説）

    var notes: [Note] { // 外部に露出するnotes
        get { // 保持者の値をidsInOrderでsortしてget
            var arr = [Note]()
            var elesToCheck = _notes

            for id in idsInOrder {
                guard let idx = elesToCheck.firstIndex(where: {$0.id ==  id}) else { continue }
                arr.append(elesToCheck[idx])
                elesToCheck.remove(at: idx)
            }
            return arr
        }
        set { // [Note]を保持者に、それらidをidsInOrderに与える。
            idsInOrder = newValue.map { $0.id }
            _notes = newValue
        }
    }

    init(timestamp: Date, notes: [Note]) {
        self.timestamp = timestamp
        self.idsInOrder = notes.map { $0.id }
        self._notes = notes

    }
}

@Model
final class Note: Identifiable {
    var value: String
    var id = UUID() // idを保持
    init(value: String) {
        self.value = value
    }
}
```

`PersistentModel`準拠型はIdentifierbleであり、`PersistentIdentifier.ID`の活用を考えたが、`PersistentIdentifier.ID`は`PersistentModel`に準拠していないためできない旨のエラーが出た。