2

I am currently working with SwiftUI and CoreData.

Situation: I have a User Detail View with a Delete Button. When pressed, the Core Data Entry of the User is getting deleted and the App Navigation goes back to the Root Navigation View, which is a List of all Users.

Problem: Every Time the Delete Button is clicked the App crashes with the following Error Message:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[User timeCreated]: unrecognized selector sent to instance 0x2802ffa40'

My Guess: I guess the Problem has something to do with the Fact, that I use a @ObservedObject Property Wrapper for the User Object (look Code below). This is also updating on Delete which obviously causes some Problems.

import SwiftUI

struct UserView: View {
    @FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \User, ascending: false)], animation: .default) private var users: FetchedResults<User>
    
    var body: some View {
        NavigationView {
            List {
                ForEach(users) { user in
                    NavigationLink(destination: UserDetailView(user: user)) {
                        Text(user.name)
                    }
                }
            }
        }
    }
}

struct UserDetailView: View {
    @Environment(\.managedObjectContext) var context
    @Environment(\.presentationMode) var mode: Binding<PresentationMode>
    
    @ObservedObject var user: User
    
    var body: some View {
        Button(action: { deleteUser() }) {
            Text("Delete")
        }
    }
    
    private func deleteUser() {
        context.delete(user)
            
        do {
            try context.save()
            
            // Navigate Back to List View
            self.mode.wrappedValue.dismiss()
                
        } catch let error as NSError {
            print("Error deleting Item from Core Data: \(error), \(error.userInfo)")
        }
    }
}

Question: How can I delete the User and return to the Root List View without an App Crash? (Note: Obviously the most easiest Solution would be to make user a normal Property, however, I need the automatic Update Behaviour since there is also a Update User View which may change some of the Content)

Thanks for your Help.

christophriepe
  • 1,157
  • 12
  • 47

1 Answers1

1

I'm not sure that the issue is in provided code... but try the following (not tested - just idea - defer deleting):

private func deleteUser() {
    mode.wrappedValue.dismiss()

    DispatchQueue.main.async {
      context.delete(user)
      do {
        try context.save()
      } catch let error as NSError {
          print("Error deleting User from Core Data: \(error), \(error.userInfo)")
      }
   }
}
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • Thanks for your Answer, however the App is still crashing. Do you have another Idea? – christophriepe Dec 16 '20 at 18:16
  • Well... then I think the reason is not in this code. Could you give access to a project or prepare small reproducible demo? – Asperi Dec 16 '20 at 18:21
  • If this help I can do so. However, Could't the Error be, that in the Moment u delete the User, the ObservedObject Property tries to Update and produces an App Crash bc. the corresponding CoreData Entry was deleted? – christophriepe Dec 16 '20 at 18:23
  • Maybe if you have directly binding to its properties somewhere else in the code. – Asperi Dec 16 '20 at 18:25
  • I updated the Question above with the full Code for this. Can you spot any Error? – christophriepe Dec 16 '20 at 18:38
  • I've just created simple CoreData project and used your code instead of automatically generated - crash is not reproduced. Xcode 12.1 / iOS 14.1. – Asperi Dec 16 '20 at 19:02
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/226060/discussion-between-christophriepe-and-asperi). – christophriepe Dec 16 '20 at 19:08