SwiftUIでCoreDataを使う

CoreDataを使ってToDoリストを作成する。

目次

クラスを作成する

デフォルトではItemEntitiesのみ存在する。

Entitiesは選択してDeleteキーで削除、Todo用のタスクを作成した。

ContentView.swift

以下のコードだけでアプリが実装できる。

  • タスクの追加、削除
  • TapGestureのところは、タスクにチェックをつけるための処理
  • FetchRequestでタイムスタンプの順番にタスク一覧を取得できtasksに格納される。
import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext
    
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Task.timestamp, ascending: true)],
        animation: .default)
    
    private var tasks: FetchedResults<Task>
    
    var body: some View {
        
        NavigationView{
            
            List {
                ForEach(tasks) { task in
                    HStack{
                        Image(systemName: task.checked ? "checkmark.circle.fill" : "circle")
                        Text("\(task.name!)")
                        Spacer()
                    }
                    
                    .contentShape(Rectangle())
                    .onTapGesture {
                        task.checked.toggle()
                        try? viewContext.save()
                    }
                    
                }
                .onDelete(perform: deleteItems)
            }
            .navigationTitle("やることリスト")
            
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    EditButton()
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    NavigationLink(destination: AddTaskView()){
                        Image(systemName: "plus")
                    }
                }
            }
        }
    }
    
    private func deleteItems(offsets: IndexSet) {
        for index in offsets {
            viewContext.delete(tasks[index])
        }
        try? viewContext.save()
    }
}

struct AddTaskView: View {
    @Environment(\.managedObjectContext) private var context
    @Environment(\.presentationMode) var presentationMode
    @State private var task = ""
    
    var body: some View {
        Form {
            Section() {
                TextField("タスクを入力", text: $task)
            }
        }
        .navigationTitle("タスク追加")
        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                Button("保存") {
                    let newTask = Task(context: context)
                    newTask.timestamp = Date()
                    newTask.checked = false
                    newTask.name = task
                    
                    try? context.save()
                    
                    presentationMode.wrappedValue.dismiss()
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
    }
}

 

Previewで表示する

Persistence.swiftで以下のように初期データを入れておかないと、Previewでクラッシュした。

    static var preview: PersistenceController = {
        let result = PersistenceController(inMemory: true)
        let viewContext = result.container.viewContext
        
        let newTask = Task(context: viewContext)
        newTask.timestamp = Date()
        newTask.checked = false
        newTask.name = "ダミータスク"
        
        do {
            try viewContext.save()
        } catch {

参考

https://capibara1969.com/3242/