既存プロジェクトにCoreDataを入れる(CoreData 手習い#1)

既存プロジェクトにCoreDataを入れるCoreData

CoreData 手習いその1です。

CoreDataの中途採用

最初からCoreDataを用意するのではなく、途中から導入するケースです。なお、SwiftUIを使っています。

使うつもりがないなら、チェックなんて入れないですよね……

CoreDataを使うつもりでなかった既存プロジェクトにCoreDataを突っ込んでいきましょう。

なお、CoreDataを使うおニュープロジェクトから差分的なものをそのまんま何も考えず既存プロジェクトに持ってくると、いろいろとエラーが出てしまいました。予想の範囲内なので、とりあえずはそっ閉じして仕切り直しです。

適当よくない。

エンティティファイルを追加する

これが件のファイルですね。

Data Modelというものを追加します。どんなデータを保存するかにより、わかりやすい名前にしましょう。
ここではTestData.xcdatamodeldとしました。

AppDelegate.swiftを編集する

ここですることは、

  • import文の追加
  • NSPersistentContainerを取得する
  • データの保存メソッドを作る

です。

// import文の追加
import CoreData
// NSPersistentContainerの取得
lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "追加したData Modelの名前")
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            // 適宜エラー処理
        }
    })
    return container
}()
// データの保存メソッド
func saveContext () {
    let context = persistentContainer.viewContext
    if context.hasChanges {
        do {
            try context.save()
        } catch {
            let nserror = error as NSError
            // 適宜エラー処理
        }
    }
}

ところで、データの保存メソッドはなぜここにいるのか?後で別クラスにだしてもいいかと思います。
と申しますか、(個人的な思想信条の関係上)後で別クラスに切り分けてみます。

SceneDelegate.swiftを編集する

これまで見かけなかったファイルですね。改めてどういうものか軽めに確認しておきます。

  • iOS13からiPadOSで利用できるマルチウィンドウをサポートするために使われる。
  • これまでAppDelegate.swiftで取り扱われていた処理が分離された。
  • シーンを制御するためのメソッドが追加されている

つまるところ、シーン周りの管理をするものを独立させたものです(とても乱暴なまとめ)

ここへCoreDataに関連するコードをお邪魔させます。

  • (おそらく)新しくシーンを作るメソッドに、AppDelegate.swiftにて取得したNSPersistentContainerのコンテキストを使えるようにする
  • (おそらく)シーンがバッググラウンドに行ってしまったときに未保存のデータを取りまとめて保存してしまうようにする
// (おそらく)新しくシーンを作るメソッドに、`AppDelegate.swift`にて取得したNSPersistentContainerのコンテキストを使えるようにする
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // AppDelegate.swiftにて取得したNSPersistentContainerのコンテキストを持ってくる
    let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    // 表示させるビューに対して環境値を設定する(ここではmanagedObjectContextというキーに対して、managedObjectContextを設定)
    // CoreDataを取り回す際に頻繁に出てくるような気配がするので、このキーは重要と思われる
    let contentView = ContentView().environment(\.managedObjectContext, managedObjectContext)
    〜(略)〜
}
    〜(略)〜
// (おそらく)シーンがバッググラウンドに行ってしまったときに未保存のデータを取りまとめて保存してしまうようにする
func sceneDidEnterBackground(_ scene: UIScene) {
    // 保存処理
        (UIApplication.shared.delegate as? AppDelegate)?.saveContext()
}

「おそらく」とはなんとも弱気な書きようですな

並んでいるメソッドを眺めて、なんとなくシーンのライフサイクルを表しているような感じがしたので、「おそらく」そうだろーなと判断したためです。使っているうちにそのうち慣れてくるでしょう。

本日はここまで

このままでは「コンテキスト」というものができただけで、どういったデータを扱うかが分かりません。
次はそれを定義していきます。

次を書きました

タイトルとURLをコピーしました