CoreDataを使う
CoreDataは、いまだに人気がある
Core Data
Persist or cache data on a single device, or sync data to multiple devices with CloudKit.
Overview
Use Core Data to save your application’s permanent data for offline use, to cache temporary data, and to add undo functionality to your app on a single device. To sync data across multiple devices in a single iCloud account, Core Data automatically mirrors your schema to a CloudKit container.
Through Core Data’s Data Model editor, you define your data’s types and relationships, and generate respective class definitions. Core Data can then manage object instances at runtime to provide the following features.
コア・データ
CloudKitを使用して、1つのデバイスにデータを永続化またはキャッシュしたり、複数のデバイスにデータを同期したりできます。
概要
Core Data を使用すると、アプリケーションの永続的なデータをオフラインで使用できるように保存したり、一時的なデータをキャッシュしたり、1 つのデバイス上のアプリケーションにアンドゥ機能を追加したりできます。1つのiCloudアカウントで複数のデバイスにわたってデータを同期するために、Core DataはCloudKitコンテナにスキーマを自動的にミラーリングします。
Core Dataのデータモデルエディタを通じて、データの型とリレーションシップを定義し、それぞれのクラス定義を生成します。Core Dataは実行時にオブジェクトインスタンスを管理し、以下の機能を提供します。
標準機能で入ってる。設定は意外と難しくない???。久しぶりに触ってみた。昔は、UIKitで使いましたね。
この動画見れば参考になった
モデルの設定
import CoreData
struct PersistentController {
let container: NSPersistentContainer
init() {
container = NSPersistentContainer(name: "MyCoreData")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolve error \(error)")
}
})
}
}
エントリーポイントに設定
import SwiftUI
@main
struct CoreDataTutorialApp: App {
let persistenceController = PersistentController()
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
}
}
}
アプリのコード
少しアレンジしてみた。チェックしたデータだけ削除するリマインダーアプリのタスク機能のようなものにした。
import SwiftUI
import CoreData
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Human.name, ascending: true)])
private var humans: FetchedResults<Human>
@State private var name = ""
var body: some View {
VStack {
HStack {
TextField("人間の名前", text: $name)
Button(action: addHuman) {
Text("保存")
}
}
.padding()
List {
ForEach(humans) { human in
HStack {
Button(action: { toggleChecked(human) }) {
Image(systemName: human.checked ? "checkmark.square" : "square")
}
Text(human.name ?? "")
}
}
}
Button(action: deleteCheckedHumans) {
Text("チェックした項目を削除")
}
.padding()
}
}
private func addHuman() {
withAnimation {
let newHuman = Human(context: viewContext)
newHuman.name = name
newHuman.checked = false
saveContext()
name = ""
}
}
private func toggleChecked(_ human: Human) {
withAnimation {
human.checked.toggle()
saveContext()
}
}
private func deleteCheckedHumans() {
withAnimation {
humans.forEach { human in
if human.checked {
viewContext.delete(human)
}
}
saveContext()
}
}
private func saveContext() {
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
動作はこんな感じ
まとめ
最近は、SwiftDataを使っているのですが、古いOSにも対応するアプリを作るとなると、サポートされているCoreDataを選択すると思うので、こちらの方が良いでしょう。
Discussion