Skip to main content
  1. Posts/

NSManagedObjectのインスタンスをViewContext(ほぼ)なしで生成する

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:)に渡してあげます。重要なポイントは、insertIntonilを指定することです。こうすることで、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に管理させることができます。

以上です。