I build a simple ToDo app using Realm. I wrote a RealmManager to handle CRUD actions and I have some views that use it.
That's the git repo: https://github.com/AlessioPoggi99/ToDo
RealmManager has a @Published var that's an array with all the tasks and I'm using the RealmManager as a @EnvironmentObject so I have access to tasks array in my views.
This is the main view code:
//
// TasksView.swift
// ToDo
//
// Created by Alessio Poggi on 28/11/22.
//
import SwiftUI
struct TasksView: View {
@EnvironmentObject var realmManager: RealmManager
var body: some View {
VStack {
Text("My tasks")
.font(.title2).bold()
.padding(.horizontal)
.padding(.top)
.frame(maxWidth: .infinity, alignment: .leading)
if realmManager.tasks.count > 0 {
List {
ForEach(realmManager.tasks, id: \.id) { task in
if !task.isInvalidated && !task.isFrozen {
TaskRow(task: task.title, completed: task.completed)
.onTapGesture {
realmManager.updateTask(id: task.id, completed: !task.completed)
}
.swipeActions {
Button(role: .destructive) {
realmManager.deleteTask(id: task.id)
} label: {
Label("Delete", systemImage: "trash")
}
}
}
}
.listRowSeparator(.hidden)
}
.scrollContentBackground(.hidden)
}
Spacer()
}
}
}
Problem
The problem is that every time I use the swipeActions to delete the task, the app crashes with this error 'RLMException', reason: 'Object has been deleted or invalidated.'
The fact is that I found some solutions, instead of using swipeActions. The fist solution is to use a simple button below each 'TaskRow' and using the same delete method.
The second solution I found is using .onDelete on the forEach cycle, and using again the same delete method:
List {
ForEach(realmManager.tasks, id: \.id) { task in
if !task.isInvalidated && !task.isFrozen {
TaskRow(task: task.title, completed: task.completed)
.onTapGesture {
realmManager.updateTask(id: task.id, completed: !task.completed)
}
}
}
.onDelete { indexSet in
indexSet.forEach { index in
let taskTodelete = realmManager.tasks[index]
realmManager.deleteTask(id: taskTodelete.id)
}
}
.listRowSeparator(.hidden)
}
Question
The delete method works well, and I implemented 2 ways to use it, so the question is: Why does the app crash when using the delete method inside .swipeActions ?