見出し画像

[iOS] SwiftUI + CoreDataを使ってみた

最近個人アプリを開発しています。
アプリ内に入れたい機能の一つが「目覚まし時計(アラーム)」なのです。

アラーム一覧を実装させるためにはデータのCRUD(照会、追加、削除、更新)が必要なため端末内に保持できるいろんな方法を調べてみましたが、結果的にはSwiftUIとCore Dataを利用したデータ管理を導入することにしました。

今回はCore Dataを活用してデータを管理する方法を簡単に共有したいと思います。

1. CoreData生成

プロジェクトを生成する時は"Use Core Data"にチェックを入れます。
あとで追加することもできますが、最初からチェックをしておくと自動でモデルファイル(.xcdatamodel)を生成してくれるので楽です。

スクリーンショット 2022-01-31 18.44.47

2. モデル作成

(1) .xcdatamodelファイルを開いて、「Add Entity」でEntity(MVVMのModelクラス的なものになります)を追加します。

スクリーンショット 2022-01-31 18.56.00

(2) Entityをクリックし、「+」ボタンで属性を追加します。

なんかDBのTableみたいな感じがする

これで別のクラスファイルを作成せずにモデルが使えるようになります。

3. CoreDataのコードセット

(1) Persistence.swiftのNSPersistentContainerにデータモデル名を指定します。
最初からデータモデルが作られているとここのnameに自動で入っていると思いますが、あとでデータモデルを追加したり、データモデルを変更した場合は必ずこちらを先に修正してください。ここのnameが違うとビルドエラーになります。

import CoreData

struct PersistenceController {
    static let shared = PersistenceController()

    // Previewが必要な場合もここにコードを書く

    let container: NSPersistentContainer

    init(inMemory: Bool = false) {
        container = NSPersistentContainer(name: "データモデル名") 
        if inMemory {
            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
        }
        ..省略..
    }
}

(2) CRUDメソッドを作成します。
各ViewごとにViewModelを作ってその中に各機能のメソッドを定義するか、機能を全部まとめて定義したクラスを用意するか自分の好みや必要に応じてやってもらってOKです。

  • 追加
    context.save()を利用します。

func createAlarm(time: Date, context: NSManagedObjectContext) {
        let newAlarm = Alarm(context: context)
        newAlarm.id = UUID()
        newAlarm.time = time
        newAlarm.label = label
        newAlarm.isActive = true
        newAlarm.createdAt = Date()

        do {
            try context.save()
        }
        catch {
            print(error.localizedDescription)
                }
}
  • 照会
    @FetchRequestで照会するEntityの指定、ソートなどを指定することができます。
    リクエストされた結果はFetchedResults<Entity名>で持ってくることができます。

  • 削除
    context.delete()を利用します。
    削除した後は必ずsave()で保存することがポイントです。

struct AlarmListView: View {
    @Environment(\.managedObjectContext) var context
    @FetchRequest(
        entity: Alarm.entity(),
        sortDescriptors: [NSSortDescriptor(keyPath: \Alarm.createdAt, ascending: false)],
        predicate: nil
    )
    private var alarms: FetchedResults<Alarm>
    
    var body: some View {
        NavigationView {
            VStack {
                List {
                    ForEach(alarms) { alarm in
                        AlarmView(alarm: alarm)
                    }
                    .onDelete(perform: self.deleteAlarm)
                }
                .listStyle(.plain)
            }
                  }
     }

    // データ削除メソッド
    func deleteAlarm(offsets: IndexSet) {
        for index in offsets {
            context.delete(alarms[index])
        }
        try? context.save()
    }
}

最後に

実際のコードはもっと長くてここでは全部紹介できなかったのですが、CoreDataの基本的な使い方はある程度コードで紹介できたかなと思います。
こういった使い方さえ知っておくと、簡単なアプリを作るときにもう少し幅が広くなると思いますのでぜひ試してみてください!

参考

この記事が気に入ったらサポートをしてみませんか?