こんにちは.
Sadmachineです.
この記事ではアプリ開発の基礎...
CoreDataの読み書きをわかりやすく解説していきます!
スクリーンショットも適宜つけるので参考にしてください!
前回の記事では
Xcodeプロジェクトの開始〜CoreDataの初期設定までをわかりやすく解説しました!
前回の記事:この素晴らしいSwiftUIにCoreDataを!【初期設定編】
LGTMたくさんしてね!!!
目次
- [おさらい:0. 開発環境](## 0. 開発環境)
- [3. CoreDataの読み書きをしてみよう](## 3. CoreDataの読み書きをしてみよう)
- [まとめ](## まとめ)
おさらい : 0. 開発環境
筆者の開発環境をめっちゃ簡単に紹介します.
- Xcode 12.3
- SwitfUI
以上.
もっと詳しく知りたい人はTwitterに凸して,どうぞ.
3. CoreDataの読み書きをしてみよう
前回の記事:この素晴らしいSwiftUIにCoreDataを!【初期設定編】の設定のままではエラー吐かれがちなので修正します.
※以下のソースのMugenMemoは適宜自分のProductNameに読み替えて進めてください.
3-1 CoreDataを動かすためのエラー修正
以下の2つのコードを修正します.
Persistence.swift (絶対修正が必要)
MugenMemoApp.swift (場合によっては修正が必要)
ほとんどの場合,Persistence.swiftの修正のみで済むと思います.
Persistence.swiftの修正
↑図の16~19行目を削除またはコメントアウトするだけです.Persistence.swiftは以下のようにすればOK.
import CoreData
struct PersistenceController {
static let shared = PersistenceController()
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
//
//ここら辺にあるfor文をコメントアウトにするか削除
//
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
let container: NSPersistentCloudKitContainer
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "MugenMemo")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
}
}
MugenMemoApp.swiftの修正
もし,ProductNameApp.swiftでエラーを吐かれたら
.environment(.managedObjectContext, persistenceController.container.viewContext)
の部分に色が付いていないことが原因であることが多いです.
.environmentの1行を切り取り,元あった場所に貼り付ければ.environment部分に色がつき,大体解決します.
一応コードも以下に載せておきます.
import SwiftUI
@main
struct MugenMemoApp: App {
let persistenceController = PersistenceController.shared
var body: some Scene {
WindowGroup{
ContentView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
}
}
}
以上でエラーを吐かないで動いてくれるようになります.
3-2 CoreDataにデータを追加
流れとしては
-
CoreDataにデータを書き込む準備
→ SwiftUIでCoreDataにデータを追加する「+ボタン」を実装 -
CoreDataにデータを書き込む・読み込んで表示させる
→ +ボタンを押すとCoreDataにデータを追加する処理を実装
→ ContentView.swiftにList形式でCoredataの中身を表示させる処理の実装 - エミュレーターでテストして動作を確認する
それではやっていきましょう.
CoreDataにデータを書き込む準備
→ SwiftUIでCoreDataにデータを追加する「+ボタン」を実装
この時点では押しただけでは何も起きないです.
もちろんCoreDataにも何も追加されません.
ContentView.swiftを以下のように編集します.
import SwiftUI
import CoreData
struct ContentView: View {
// 編集箇所①
@Environment(\.managedObjectContext) var moc
@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Memo.title, ascending: true)],animation: .default) var Data: FetchedResults<Memo>
var body: some View {
NavigationView {
List {
Text("TEST")
}
// 編集箇所②
.navigationTitle("Test")
.navigationBarTitleDisplayMode(.inline)
.navigationBarItems(trailing: Button(action: {
// ここにアクションを書く
}) {
Image(systemName: "plus")
}
)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
保存してResumeを押すと...
Canvas上でこうなるはずです. こうなっていればOK!CoreDataにデータを書き込む・読み込んで表示させる
→ +ボタンを押すとCoreDataにデータを追加する処理を実装
→ ContentView.swiftにList形式でCoredataの中身を表示させる処理の実装
以下がCoreDataに指定した文字列を追加し,Listに表示するコードです.
import SwiftUI
import CoreData
struct ContentView: View {
@Environment(\.managedObjectContext) var moc
@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Memo.title, ascending: true)],animation: .default) var Data: FetchedResults<Memo>
var body: some View {
NavigationView {
List {
// Text("TEST")をForEach文に変更.
// CoreDataの中身を表示している,
ForEach(Data, id: \.self) { i in
Text(i.title!)
}
}
.navigationTitle("Test")
.navigationBarTitleDisplayMode(.inline)
// +ボタンとCoreDataにデータを追加する処理を紐づける
.navigationBarItems(
trailing:
Button(action: {
create()
}) {
Image(systemName: "plus")
}
)
}
}
// CoreDataにデータ(今回は文字列"I LOVE Swift")を追加する処理を実装
func create() {
let t = Memo(context: moc)
t.title = "I LOVE Swift"
do {
try moc.save()
} catch {
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
エミュレーターでテストして動作を確認する
赤く囲われた部分のiPhone11というところを押すとエミュレーターの機種が選べます. 選んだら左の再生ボタンを押してエミュレーター上でビルドしてみましょう. ↑図のようになっていればエミュレーターの起動とアプリのビルドは成功です. 試しに+ボタンを押してみると...I LOVE Swiftという項目が追加されました.
試しにアプリを落としてみてもI LOVE Swiftは保持されたままです.
CoreDataへの追加は成功です!
やったぜ.
ちなみに,+ボタンを連打しまくるとI LOVE SwiftがListに量産されます.
まとめ
CoreDataの読み書きをわかりやすく解説しました.
今回はここまで.
次回は,
CoreDataのデータの削除とSwiftUIにおける削除UIの実装
の予定です.
SwiftUIの削除UIを導入してCoreDataのデータを削除できるようにします.
結構簡単に実装できるので次回もお付き合いください.
備忘録的なまとめですが,誰かの参考になれば嬉しいです.
少しでも参考になりましたらLGTMやフォロー,Twitterでの拡散をしてください!
喜びます.