[CoreData] CoreData での便利なライブラリ

CoreDataStackがObsoleteだと気づいて、別の便利なライブラリを探していて見つけました。

JSQCoreDataKit

Xcodeでプロジェクトを作ると、テンプレートとして、AppDelegateにCoreDataのコードが追加されます。

どこをみても、AppDelegateに置くのは筋が良くないと書いてあります。

SwiftUIであれば、environmentを使って、NSManagedObjectContextは、ビュー階層には渡せますが、
Viewではないクラスに渡したいときに、常にAppDelegate経由になるのは、あまり推奨されないと思います。

でも、自分で、CoreData系の情報を集めるクラスを1から作るのも、車輪の再発明っぽくて、躊躇してました。

ということで見つけたのが、JSQCoreDataKitです。

適当なところで、以下のコードを使うと、CoreDataがセットアップされます。

modelNameは、デフォルトでは、プロジェクトの名前が設定されているxcdatamodeldのことです。
Bundleは、上記のモデルがふくまれているBundleです。これもデフォルトでは、mainのBundleとなります。

コード

let model = CoreDataModel(name: modelName, bundle: modelBundle)
let factory = CoreDataStackProvider(model: model)
factory.createStack { result in
    switch result {
    case .success(let s):
        self.stack = s
    case .failure(let err):
        assertionFailure("Error creating stack: \(err)")
    }
}

上記の.successで渡されるsを保持しておけば、終了です。stack.mainContextがManagedObjectContextです。(必要に応じて、childContextも作れます)

ちなみに、SwiftUIの場合は、EnvironmentにManagedObjectContextをビュー構築時に渡す必要があるので、factoryの結果を待つ必要があります。なので、以下のようなコードで実行する必要があります。
# asyncでセットアップを実行してしまうと、environmentに渡そうと取得したタイミングが、初期化前のために、エラーとなるケースがあります。(タイミングの問題なので、100%ではないですが、ほぼエラーとなります)

コード

let model = CoreDataModel(name: "CoreDataModel")
let factory = CoreDataStackProvider(model: model)
factory.createStack(onQueue: nil, completion: { result in
    switch result {
    case .success(let s):
        // store CoreDataStack in somewhere
        self.coreDataStack = s
    case .failure(let err):
        assertionFailure("Error in creating stack: \(err)")
    }
})
// Get the managed object context from the shared persistent container.
let context = coreDataStack.mainContext

// Create the SwiftUI view and set the context as the value for the managedObjectContext environment keyPath.
// Add `@Environment(\.managedObjectContext)` in the views that will need the context.
let contentView = ContentView().environment(\.managedObjectContext, context)

P.S.
このライブラリのサンプルを見ての通りですが、CoreDataのモデルだけのプロジェクト/Bundleを作っています。

このアイデアも良い感じでした。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です