To provide a little bit of information of what I am trying to do:
I have two CoreData entities that have a One-To-Many relationship:
Tarantula - A tarantula may molt many times (To Many) and when deleted, all of the molts shold also be removed (Cascade)
Molt - A molt belongs to a single Tarantula (To One) and when
deleted, should have the reference removed from the Tarantula (Nullify)
I then have a view that lists all of the molts for a given Tarantula that allows adding and deleting molts. It looks like this:
Code Block swift struct MoltListView: View { private static let DATE_FORMATTER: DateFormatter = { let d = DateFormatter() d.dateFormat = "MMM d, y" return d }() @Environment(\.managedObjectContext) private var viewContext @ObservedObject private var tarantula: Tarantula @FetchRequest private var molts: FetchedResults<Molt> @State private var userMessage: String = "" @State private var displayMessage: Bool = false init(tarantula: Tarantula) { self.tarantula = tarantula self._molts = FetchRequest(entity: Molt.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Molt.date, ascending: false)], predicate: NSPredicate(format: "tarantula = %@", tarantula)) } var body: some View { List { Section(header: Text("Summary")) { Text("\(molts.count) Molt\(molts.count == 1 ? "" : "s")") } Section(header: Text("Molts")) { NavigationLink(destination: MoltView(tarantula: tarantula, molt: Molt.newModel())) { Text("Add Molt").foregroundColor(.blue) } ForEach(molts, id: \.self) { molt in NavigationLink(destination: MoltView(tarantula: tarantula, molt: molt)) { Text(MoltListView.DATE_FORMATTER.string(from: molt.modelDate)) } } .onDelete(perform: deleteItems) } }.alert(isPresented: $displayMessage) { Alert(title: Text("Save Failure"), message: Text(userMessage), dismissButton: .default(Text("Ok"))) } } private func deleteItems(offsets: IndexSet) { withAnimation { offsets.map { molts[$0] }.forEach(viewContext.delete) do { try viewContext.save() } catch { viewContext.rollback() userMessage = "\(error): \(error.localizedDescription)" displayMessage.toggle() } } } }
The error I am experiencing comes from whenever I try to delete a molt from the list view. The app instantly crashes and the error is:
Code Block swift Simultaneous accesses to 0x7f92efc61cb8, but modification requires exclusive access
Find the complete error here:
I have tried removing the animation block and have played around with removing different UI components/restructuring.
The only way I have been able to prevent this error is to remove the delete rule on the Molt->Tarantula relationship from Nullify to No Action. However, this seems more like a hack to me instead of a fix.
Was hoping for some help on this issue.
The behavior you've reported is the result of a system bug, and should be fixed in a future release. As a workaround, you can prevent the race condition by wrapping your deletion logic in NSManagedObjectContext.perform:
Code Block swift private func deleteItems(offsets: IndexSet) { withAnimation { viewContext.perform { offsets.map { molts[$0] }.forEach(viewContext.delete) do { try viewContext.save() } catch { viewContext.rollback() userMessage = "\(error): \(error.localizedDescription)" displayMessage.toggle() } } } }
Please let me know if the information above does not resolve your issue(s).
Cheers,
Paris