[iOS] SwiftUI + CoreDataを使ってみた
最近個人アプリを開発しています。
アプリ内に入れたい機能の一つが「目覚まし時計(アラーム)」なのです。
アラーム一覧を実装させるためにはデータのCRUD(照会、追加、削除、更新)が必要なため端末内に保持できるいろんな方法を調べてみましたが、結果的にはSwiftUIとCore Dataを利用したデータ管理を導入することにしました。
今回はCore Dataを活用してデータを管理する方法を簡単に共有したいと思います。
1. CoreData生成
プロジェクトを生成する時は"Use Core Data"にチェックを入れます。
あとで追加することもできますが、最初からチェックをしておくと自動でモデルファイル(.xcdatamodel)を生成してくれるので楽です。
2. モデル作成
(1) .xcdatamodelファイルを開いて、「Add Entity」でEntity(MVVMのModelクラス的なものになります)を追加します。
(2) Entityをクリックし、「+」ボタンで属性を追加します。
これで別のクラスファイルを作成せずにモデルが使えるようになります。
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の基本的な使い方はある程度コードで紹介できたかなと思います。
こういった使い方さえ知っておくと、簡単なアプリを作るときにもう少し幅が広くなると思いますのでぜひ試してみてください!