title: SwiftUI App Crashing EXC_BAD_ACCESS error when coredata list items are deleted
body: <p>The following code is working all the way until the delete operation is done on list items. But this is not occurring every time the code is running. It crashes with <code>EXC_BAD_ACCESS</code> code of thread error:</p>
  <p><a href="https://i.stack.imgur.com/aQA3V.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/aQA3V.png" alt="ERROR" /></a></p>
  <p>Then I realized, this error is occurring after a certain time after delete operation if the app is kept running</p>
  <p>This is why this error is very confusing to figure out. But it started appearing when I added <code>DispatchQueue.main.async</code> method to <code>tasks</code> in <code>Model.swift</code>.</p>
  <p>The purpose of this code is to reload updated results from core data using <code>self.fetchAll()</code> method when there is any change happened in the list.</p>
  <p><a href="https://i.stack.imgur.com/fMh4S.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/fMh4S.png" alt="Red Line on Delete" /></a></p>
  <p>Another problem I noticed is the red lines appearing after deleting.</p>
  <p>Questions:</p>
  <ol>
  <li>How to update content view struct with least code when a core data list is updated? (This <a href="https://github.com/nikhiljohn10/CoreData-MacOS" rel="nofollow noreferrer">link</a> has a different approach by the fetch method is called every time explicitly in code.)</li>
  <li>How to optimize this code with less code and more stability?</li>
  <li>Is the red line issue from the picture is part of an existing macOS bug?</li>
  </ol>
  <blockquote>
  <p>macOS: 10.15.4</p>
  <p>XCode: 11.5</p>
  <p>Target: 10.15</p>
  </blockquote>
  <p><strong>Model.swift</strong></p>
  <pre><code>import Foundation
  import CoreData
  
  class Model: ObservableObject {
      @Published var context: NSManagedObjectContext
      @Published var tasks: [Task] = [Task]() {
          didSet {
              DispatchQueue.main.async {
                  self.fetchAll()
              }
          }
      }
      init(_ viewContext: NSManagedObjectContext) {
          context = viewContext
      }
  }
  
  // MARK: Methods
  
  extension Model {
      func fetchAll() {
          let req = Task.fetchRequest() as NSFetchRequest&lt;Task&gt;
          req.sortDescriptors = [NSSortDescriptor(keyPath: \Task.name, ascending: true)]
          do {
              self.tasks = try self.context.fetch(req)
          } catch let error as NSError {
              print(error.localizedDescription)
          }
      }
      
      func addTask(_ text: String) {
          let name = text.trimmingCharacters(in: .whitespacesAndNewlines)
          if (name != &quot;&quot;) {
              let task = Task(context: self.context)
              task.id = UUID()
              task.name = name
              task.creationTimestamp = Date()
              task.updatedTimestamp = Date()
              self.context.insert(task)
              self.save()
          }
      }
      
      func save() {
          guard self.context.hasChanges else { return }
          do {
              try self.context.save()
              print(&quot;Saved changes&quot;)
          } catch let error as NSError {
              print(error.localizedDescription)
          }
      }
  }
  </code></pre>
  <p><strong>AppDelegate.swift</strong></p>
  <pre><code>import Cocoa
  import SwiftUI
  
  @NSApplicationMain
  class AppDelegate: NSObject, NSApplicationDelegate {
  
      var window: NSWindow!
      var model: Model!
      
      func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -&gt; Bool {
          return true
      }
      
      func applicationDidFinishLaunching(_ aNotification: Notification) {
          
          model = Model(persistentContainer.viewContext)
          let contentView = ContentView().environmentObject(model)
  
          window = NSWindow(
              contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
              styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
              backing: .buffered, defer: false)
          window.center()
          window.setFrameAutosaveName(&quot;Main Window&quot;)
          window.contentView = NSHostingView(rootView: contentView)
          window.makeKeyAndOrderFront(nil)
      }
  
      func applicationWillTerminate(_ aNotification: Notification) { }
  
      // MARK: - Core Data stack
  
      lazy var persistentContainer: NSPersistentCloudKitContainer = {
          let container = NSPersistentCloudKitContainer(name: &quot;Todo_List&quot;)
          container.loadPersistentStores(completionHandler: { (storeDescription, error) in
              if let error = error {
                  fatalError(&quot;Unresolved error \(error)&quot;)
              }
          })
          container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
          container.viewContext.undoManager = nil
          container.viewContext.shouldDeleteInaccessibleFaults = true
          container.viewContext.automaticallyMergesChangesFromParent = true
          return container
      }()
  
      // MARK: - Core Data Saving and Undo support
  
      @IBAction func saveAction(_ sender: AnyObject?) {
          let context = persistentContainer.viewContext
  
          if !context.commitEditing() {
              NSLog(&quot;\(NSStringFromClass(type(of: self))) unable to commit editing before saving&quot;)
          }
          if context.hasChanges {
              do {
                  try context.save()
              } catch {
                  let nserror = error as NSError
                  NSApplication.shared.presentError(nserror)
              }
          }
      }
  
      func windowWillReturnUndoManager(window: NSWindow) -&gt; UndoManager? {
          return persistentContainer.viewContext.undoManager
      }
  
      func applicationShouldTerminate(_ sender: NSApplication) -&gt; NSApplication.TerminateReply {
          let context = persistentContainer.viewContext
          
          if !context.commitEditing() {
              NSLog(&quot;\(NSStringFromClass(type(of: self))) unable to commit editing to terminate&quot;)
              return .terminateCancel
          }
          
          if !context.hasChanges {
              return .terminateNow
          }
          
          do {
              try context.save()
          } catch {
              let nserror = error as NSError
              let result = sender.presentError(nserror)
              if (result) {
                  return .terminateCancel
              }
              
              let question = NSLocalizedString(&quot;Could not save changes while quitting. Quit anyway?&quot;, comment: &quot;Quit without saves error question message&quot;)
              let info = NSLocalizedString(&quot;Quitting now will lose any changes you have made since the last successful save&quot;, comment: &quot;Quit without saves error question info&quot;);
              let quitButton = NSLocalizedString(&quot;Quit anyway&quot;, comment: &quot;Quit anyway button title&quot;)
              let cancelButton = NSLocalizedString(&quot;Cancel&quot;, comment: &quot;Cancel button title&quot;)
              let alert = NSAlert()
              alert.messageText = question
              alert.informativeText = info
              alert.addButton(withTitle: quitButton)
              alert.addButton(withTitle: cancelButton)
              
              let answer = alert.runModal()
              if answer == .alertSecondButtonReturn {
                  return .terminateCancel
              }
          }
          return .terminateNow
      }
  }
  
  </code></pre>
  <p><strong>ContentView.swift</strong></p>
  <pre><code>import SwiftUI
  
  struct ContentView: View {
      @EnvironmentObject var model: Model
      @State var taskName: String = &quot;&quot;
      
      var body: some View {
          VStack{
              ZStack{
                  TaskList()
                      .padding(.top,31)
                  VStack(spacing:0){
                      TextField(&quot;New Task&quot;, text: self.$taskName, onCommit: {
                          self.model.addTask(self.taskName)
                          self.taskName = &quot;&quot;
                      })
                          .padding(5)
                      Divider().offset(y:-1)
                          Spacer()
                  }
                  if model.tasks.isEmpty {
                      Text(&quot;Nothing To Do\nPlease add something To Do.&quot;)
                          .multilineTextAlignment(.center)
                          .font(.headline)
                          .padding(.horizontal)
                          .frame(maxWidth: .infinity, maxHeight: .infinity)
                  }
              }
          }
          .frame(minWidth: 200, maxWidth: .infinity, maxHeight: .infinity)
          .onAppear{
              self.model.fetchAll()
          }
      }
  }
  </code></pre>
  <p><strong>TaskList.swift</strong></p>
  <pre><code>import SwiftUI
  
  struct TaskList: View {
      @EnvironmentObject var model: Model
      
      @State var selection: Task?
      
      var body: some View {
          List(selection: self.$selection){
              ForEach(self.model.tasks, id: \.self) { task in
                  TaskRow(task: task).tag(task)
              }
              .onDelete(perform: onDelete)
          }
      }
      
      private func onDelete(with indexSet: IndexSet) {
          indexSet.forEach { index in
              let task = self.model.tasks[index]
              self.model.context.delete(task)
          }
          self.model.save()
      }
  }
  </code></pre>
  <p><strong>TaskRow.swift</strong></p>
  <pre><code>struct TaskRow: View {
      @ObservedObject var task: Task
      @EnvironmentObject var model: Model
      var dateString: String {
          if let timestamp = task.updatedTimestamp {
              let formatter = DateFormatter()
              formatter.dateStyle = .long
              formatter.timeStyle = .medium
              return formatter.string(from: timestamp)
          } else {
              return &quot;No date recorded&quot;
          }
      }
      var body: some View {
          HStack {
              Toggle(isOn: Binding&lt;Bool&gt;(get: { () -&gt; Bool in
                  return self.task.checked
              }, set: { (enabled) in
                  self.task.checked = enabled
                  self.task.updatedTimestamp = Date()
                  self.model.save()
              })){
                  Text(&quot;&quot;)
              }
              VStack {
                  HStack {
                      Text(task.name ?? &quot;Unknown Task&quot;).font(.system(size: 20))
                      Spacer()
                  }
                  HStack {
                      Text(dateString).font(.system(size: 10)).bold()
                      Spacer()
                  }
              }
          }
      }
  }
  </code></pre>