NSManagedObjectのインスタンスをViewContext(ほぼ)なしで生成する
Table of Contents
NSManagedObjectのインスタンスを生成するには、主に、NSManagedObjectContext(ViewContext)を使用するinit(context:)
を使います。
しかし、SwiftUIでViewをプレビューしたいときや、データを登録せずにキャンセルする可能性があるときのように、ViewContextに管理させる前にインスタンスを作りたいことがあります。今回は、ViewContextに管理させずにNSManagedObjectを生成する方法をまとめます。忘れがちなので、備忘録です。
NSEntityDescription.entity(forEntityName:in:)でインスタンスだけを作る #
今回は Book
というNSManagedObjectクラスがあるとします。
普段通りのインスタンスを作るときは、以下のように実装します。
let book = Book(context: viewContext)
do {
try viewContext.save()
} catch {
// エラー処理
}
init(context:)
を使ってインスタンスを作ると、この時点でViewContextに管理されてしまいます。
管理させずにインスタンスを作る方法は、以下のとおりです。
let bookEntityDescription = NSEntityDescription.entity(
forEntityName: "Book",
in: viewContext // NSManagedObjectContextが必要
)
let book = Book(
entity: bookEntityDescription,
insertInto: nil // NSManagedObjectContext? なので nil 可能
)
まず、NSEntityDescription.entity(forEntityName:in:)
をつかうことで、NSManagedObjectModelのEntityを取り出すことができます。次に、取り出したEntityを、NSManagedObjectのinit(entity:insertInto:)
に渡してあげます。重要なポイントは、insertInto
でnil
を指定することです。こうすることで、ViewContextで管理しない状態で、インスタンスを生成することができます。
NSEntityDescription.entity
がいまいち分かりづらいところです。ここを詳しく知りたい場合は、「Core Data Stack」というキーワードで解説されているので、他のリソースを参照してください。
ちなみに、これはさらに備忘録ですが、Core Data Stackを構成する方法がApple Developerで解説されています。
Appのターゲットだけで実装する場合は、シンプルに「Setting up a Core Data stack | Apple Developer Documentation」で解説されている方法で問題ありません。しかし、永続化の実装を別パッケージや別ターゲットで実装している場合は、レガシーな方法「Setting up a Core Data stack manually | Apple Developer Documentation」を使います。
viewContext.insert(_:)で管理させる #
init(entity:insertInto:)
で、ViewContextをnil
にしたインスタンスは、ViewContextに管理されていません。
ViewContextに管理させることで、生成したインスタンスを保存することができます。
その実装は、以下のとおりです。
// ViewContextに管理させる
viewContext.insert(book)
// 保存する
do {
try viewContext.save()
} catch {
// エラー処理
}
NSManagedObjectContextのinsert(_:)
を呼ぶことで、ViewContextに管理させることができます。
以上です。