100 Days of SwiftUI(DAY 57(Project12 part 1))

なぜ\ .selfはForEachで機能するのですか?
Why does \.self work for ForEach?

//--------------------------
List {
    ForEach([2, 4, 6, 8, 10], id: \.self) {
        Text("\($0) is even")
    }
}
//--------------------------
struct Student: Hashable {
    let name: String
}

struct ContentView: View {
    let students = [Student(name: "Harry Potter"), Student(name: "Hermione Granger")]

    var body: some View {
        List(students, id: \.self) { student in
            Text(student.name)
        }
    }
}

NSManagedObjectサブクラスの作成
Creating NSManagedObject subclasses
Movieを選択すると、そのエンティティのさまざまなデータモデルオプションが表示されますが、特に「Codegen」というものを確認してください。これは、プロジェクトのビルド時にXcodeが管理対象オブジェクトクラスとしてエンティティを生成する方法を制御します。デフォルトでは、クラス定義になります。これをManual / Noneに変更すると、クラスの作成方法を完全に制御できます。
XcodeがMovieコードで使用するクラスを生成しなくなったので、実際に実際のSwiftコードでクラスを作成しない限り、コードでXcode を使用することはできません。これを行うには、[エディター]メニューに移動し、[NSManagedObjectサブクラスの作成]を選択します。「CoreDataProject」が選択されていることを確認し、[次へ]を押します。次に、[ムービー]が選択されていることを確認し、もう一度[次へ]を押します。Xcodeがコードを保存する場所を尋ねられるので、左側に黄色のフォルダーアイコンが表示された「CoreDataProject」を選択し、CoreDataProjectフォルダーも選択してください。準備ができたら、[作成]を押してプロセスを終了します。

Xcodeに生成されたコードを実際に表示および変更できるSwiftファイルに変換するよう依頼しただけですが、Xcodeで生成されたファイルを変更してから再生成すると、変更は失われます。

Xcodeは2つのファイルを生成しますが、気にするのはそのうちの1つ、Movie + CoreDataProperties.swiftだけです。内部には、次の3行のコードが表示されます。
さて、あなたはそのコードを見て、「そこにオプションは必要ない」と考え、これを次のように変更します。

@NSManaged public var title: String?
@NSManaged public var director: String?
@NSManaged public var year: Int16

@NSManaged public var title: String
@NSManaged public var director: String
@NSManaged public var year: Int16

代わりに、オプションの値に安全にアクセスするのに役立つ計算されたプロパティを追加することを検討することもできます。同時に、nilの結合コードをすべて1か所に格納することもできます。たとえば、これをプロパティとして追加すると、Movie常に有効なタイトル文字列が確実に処理されます。

public var wrappedTitle: String {
    title ?? "Unknown Title"
}

NSManagedObjectContextの条件付き保存
Conditional saving of NSManagedObjectContext

save()直接呼び出すのではなく、常に最初にチェックでラップする必要があります。

if self.moc.hasChanges {
    try? self.moc.save()
}

制約を使用してコアデータオブジェクトが一意であることを確認する
Ensuring Core Data objects are unique using constraints

これを試すには、「名前」という1つの文字列属性を使用して、ウィザードという新しいエンティティを作成します。次に、Wizardエンティティを選択し、データモデルインスペクターで制約を探して、すぐ下の+ボタンを押します。「カンマ、分離、プロパティ」が表示され、作業の例が示されます。それを選択し、Enterキーを押して名前を変更し、代わりに「名前」というテキストを付けます。これにより、名前属性が一意になります。変更を保存するには、Cmd + Sを押してください。


struct ContentView: View {
    @Environment(\.managedObjectContext) var moc

    @FetchRequest(entity: Wizard.entity(), sortDescriptors: []) var wizards: FetchedResults<Wizard>

    var body: some View {
        VStack {
            List(wizards, id: \.self) { wizard in
                Text(wizard.name ?? "Unknown")
            }

            Button("Add") {
                let wizard = Wizard(context: self.moc)
                wizard.name = "Harry Potter"
            }

            Button("Save") {
                do {
                    try self.moc.save()
                } catch {
                    print(error.localizedDescription)
                }
            }
        }
    }
}

あなたがいる場合したいコアデータは、変更内容を書くために、あなたはSceneDelegate.swiftを開いて、このインポートを追加する必要があります。


import CoreData

次に、この行をwillConnectToメソッドの、開始するコードのすぐ下に追加しますlet context。


context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

これは、Core Dataに、プロパティに基づいて重複オブジェクトをマージするように要求します。新しいバージョンのプロパティを使用して、データベース内のバージョンをインテリジェントに上書きしようとします。コードをもう一度実行すると、見事なものが表示されます。[追加]を何度でも押すことができますが、[保存]を押すと、Core Dataが重複を削除するため、すべてが1行に折りたたまれます。