title: onDelete causing NSRangeException
body: <p>In this app, there is a main screen (WorkoutScreen) that displays the contents of a list one at a time as it iterates through the list (current workout in a list of many). In a popOver, a list that contains all of the workouts appears and has the ability to add, delete or move items in that list.</p>
  <p>When I delete the bottom most item, there is no error. When I delete any other item in the list I get this NSRangeException error that crashes the app:</p>
  <pre><code>/*
      2022-04-24 15:41:21.874306-0400 Trellis         
      beta[9560:3067012] *** Terminating app due to     
      uncaught exception 'NSRangeException', reason: 
      '*** __boundsFail: index 3 beyond bounds [0 .. 
      2]'
      *** First throw call stack:
      (0x1809150fc 0x19914fd64 0x180a1e564 0x180a2588c 
      0x1808c0444 0x1852dcce4 0x1852e1400 0x185424670 
      0x185423df0 0x185428a40 0x18843e4a0 0x188510458 
      0x188fd83ec 0x10102f3bc 0x1010500a4 0x188494f4c 
      0x10102c664 0x10103e0d4 0x18841a944 0x10102be18 
      0x10103122c 0x18837b8ac 0x188363484 0x18834bb64 
      0x188371d20 0x1883b88e4 0x1b28fe910 0x1b28fe318 
      0x1b28fd160 0x18831e780 0x18832f3cc 0x1883f5e34 
      0x18834206c 0x188345f00 0x182eb0798 0x184613138 
      0x184605958 0x184619f80 0x184622874 0x1846050b0 
      0x183266cc0 0x1835015fc 0x183b7d5b0 0x183b7cba0 
      0x1809370d0 0x180947d90 0x180882098 0x1808878a4 
      0x18089b468 0x19c42638c 0x18323d088 0x182fbb958 
      0x1885547a4 0x188483928 0x1884650c0 0x10109a630 
      0x10109a700 0x1015b9aa4)
      libc++abi: terminating with uncaught exception 
      of type NSException
      dyld4 config: 
      DYLD_LIBRARY_PATH=/usr/lib/system/introspection 
      DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktrac 
   
  eRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/Private 
      Frameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib
      *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** 
      __boundsFail: index 3 beyond bounds [0 .. 2]'
      terminating with uncaught exception of type NSException
      (lldb)
      */
  </code></pre>
  <pre><code>struct WorkoutScreen: View {
  
      @EnvironmentObject var workoutList: CoreDataViewModel //calls it from environment
      @StateObject var vm = CoreDataViewModel()  //access on the page
      @Environment(\.scenePhase) var scenePhase
  
      var body: some View{
          //displays the current item in the list
      }
  }
  
  </code></pre>
  <p>When I add an item to the list I get the error:
  '''
  CoreData: warning: Multiple NSEntityDescriptions claim the NSManagedObject subclass 'FruitEntity' so +entity is unable to disambiguate.&quot;
  '''</p>
  <p>Moving Items without adding or deleting any prior gives me this error upon closing the pop over:
  '''
  Error saving: Error Domain=NSCocoaErrorDomain Code=133020 &quot;Could not merge changes.&quot; UserInfo={conflictList=(
  &quot;NSMergeConflict (0x2804f1480) for NSManagedObject (0x28327d900) with objectID '0x9ede5774e26501a4...
  '''</p>
  <p>Here is the core data and related functions:</p>
  <pre><code>class CoreDataViewModel: NSObject, ObservableObject {
      private let container: NSPersistentContainer
      private let context: NSManagedObjectContext
      // Whenever you put your Core Data fetch in a view model, you should use an NSFetchedResultsController.
      // This allows you to automatically update your @Published var when your Core Data store changes.
      // You must inherit from NSObject to use it.
      private let fetchResultsController: NSFetchedResultsController&lt;FruitEntity&gt;
          
      @Published var savedEntities: [FruitEntity] = []
  
      override init() {
          container = NSPersistentContainer(name: &quot;FruitsContainer&quot;)
          container.loadPersistentStores { (description, error) in
              if let error = error {
                  print(&quot;ERROR LOADING CORE DATA: \(error)&quot;)
              }
              else {
                  print(&quot;Successfully loaded core data&quot;)
              }
          }
          context = container.viewContext
          let request = NSFetchRequest&lt;FruitEntity&gt;(entityName: &quot;FruitEntity&quot;)
          let sort = NSSortDescriptor(keyPath: \FruitEntity.order, ascending: true)
          request.sortDescriptors = [sort]
          // This initializes the fetchResultsController
          fetchResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
             
          // Because you inherit from NSObject, you must call super.init() to properly init the parent class. The order of when
          // this is to be called has changed.
          super.init()
          // Because this is a delegate action, you must set the delegate. Since the view model will respond, we set the delegate to self.
          fetchResultsController.delegate = self
              
          fetchFruits()
      }
  
      func fetchFruits() {
          do {
              // Instead of calling container.viewContext.fetch(request) which is static, use fetchResultsController.performFetch()
                  try fetchResultsController.performFetch()
              // Make sure the fetch result is not nil
                  guard let fruitRequest = fetchResultsController.fetchedObjects else { return }
              savedEntities = fruitRequest
              // You do not need to let error. error is automatically captured in a do catch.
          } catch {
              print(&quot;Error fetching \(error)&quot;)
          }
       }
  
     func addFruit(text: String, nummSets: Int16, nummWeights: Int16, nummReps: Int16, secOrRepz: Bool, orderNumz: Int64, multilimbz:  Bool, countDownz: Int16, repTimez: Int16, restTimez: Int16, circuitz: Bool) {
          let newFruit = FruitEntity(context: container.viewContext)
          newFruit.name = text
          newFruit.numOFSets = nummSets
          newFruit.numOFWeight = nummWeights
          newFruit.numOFReps = nummReps
          newFruit.measure = secOrRepz
          newFruit.order = orderNumz
          newFruit.multiLimb = multilimbz
          newFruit.countDownSec = countDownz
          newFruit.timePerRep = repTimez
          newFruit.restTime = restTimez
          newFruit.circuit = circuitz
          
          saveData()
      }
  
      func deleteFunction(indexSet: IndexSet) {
          guard let index = indexSet.first else { return }
          let entity = savedEntities[index]
          container.viewContext.delete(entity)
          saveData()
      }
  
      func saveData() {
          do {
              try context.save()
              fetchFruits()
          } catch let error {
              print(&quot;Error saving: \(error)&quot;)
            }
          }
  }
  
      // This is your delegate extension that handles the updating when your Core Data Store changes.
      extension CoreDataViewModel: NSFetchedResultsControllerDelegate {
      func controllerDidChangeContent(_ controller: 
          NSFetchedResultsController&lt;NSFetchRequestResult&gt;) {
          // Essentially, you are redoing just the fetch as the NSFetchedResultsController knows how to fetch from above
          guard let fruits = controller.fetchedObjects as? [FruitEntity] else { return }
          self.savedEntities = fruits
          }
      }
  </code></pre>
  <p>Here is the list struct:</p>
  <pre><code>struct WorkoutListPopUp: View {
      
      @ObservedObject var vm = CoreDataViewModel()
      @EnvironmentObject var listViewModel: ListViewModel
      @EnvironmentObject var workoutList: CoreDataViewModel
      
      //Too many @State var to list here
      
      var body: some View {
          
          Button (action: {
              //this triggers the bug&gt;
              vm.addFruit(text: &quot;Workout name&quot;, nummSets: Int16(addSets) ?? 3, nummWeights: Int16(addWeights) ?? 0, nummReps: Int16(addReps) ?? 8, secOrRepz: addSecOrReps, orderNumz: Int64((vm.savedEntities.count)), multilimbz: dualLimbs, countDownz: 10, repTimez: 3, restTimez: 60, circuitz: false)
              loadNums()
          }, label: {
              Image(systemName: &quot;plus&quot;)
                  .resizable()
                  .aspectRatio(contentMode: .fit)
                  .frame(width:20, height: 20)
                  .foregroundColor(Color.pink.opacity(1.0))
                  .padding(.top, 0)
          })
          List(){
              ForEach(vm.savedEntities) {entity in
                  VStack{
                      EditWorkouts(entity: entity, prescribeMeasure: $prescribeMeasure, addReps: $addReps, measurePrescribed: $measurePrescribed, repTimePicker: $repTimePicker, repz: $repz, restPicker: $restPicker, setz: $setz, ready2Press: $ready2Press, workoutz: $workoutz, weightz: $weightz, setsRemaining: $setsRemaining, workoutNum: $workoutNum, workoutInstructions: $workoutInstructions, multiplelimbs: $multiplelimbs, showAllInfo: $showAllInfo)
                      
                      //are these onChanges needed if &quot;EditWorkouts&quot; file is saving?
                          .onChange(of: entity.name) { text in
                              vm.saveData()
                              loadNums()
                          }
                          .onChange(of: entity.numOFSets) { text in
                              vm.saveData()
                              loadNums()
                          }
                          .onChange(of: entity.numOFReps) { text in
                              vm.saveData()
                              loadNums()
                          }
                          .onChange(of: entity.numOFWeight) { text in
                              vm.saveData()
                              loadNums()
                          }
                          .onChange(of: entity.measure) { text in
                              vm.saveData()
                              loadNums()
                          }
                          .onChange(of: entity.order) { text in
                              vm.saveData()
                              loadNums()
                          }
                          .onChange(of: entity.circuit) { text in
                              vm.saveData()
                              loadNums()
                          }
                  }
              }
              .onDelete(perform: vm.deleteFunction)
              .onMove(perform: moveItem)
          }
          
          
          
      }
      
      func loadNums(){
          if vm.savedEntities.count &gt; 0 {
              workoutz = vm.savedEntities[workoutNum].name ?? &quot;NO Name&quot;
              setz = String(vm.savedEntities[workoutNum].numOFSets)
              weightz = String(vm.savedEntities[workoutNum].numOFWeight)
              repz = String(vm.savedEntities[workoutNum].numOFReps)
              multiplelimbs = vm.savedEntities[workoutNum].multiLimb
              prescribeMeasure = vm.savedEntities[workoutNum].measure
              if setsRemaining == 0 &amp;&amp; ((workoutNum + 1) - (Int(vm.savedEntities.count)) == 0) {
                  workoutInstructions = &quot;Goal: \(repz) \(measurePrescribed)&quot;
              }
              else {
                  workoutInstructions = &quot;Goal: \(repz) \(measurePrescribed)&quot;
              }
          }
          else {
              workoutz = &quot;Add a Workout  &quot;
              workoutInstructions = &quot; &quot;
          }
      }
      
      func moveItem(indexSet: IndexSet, destination: Int) {
          let source = indexSet.first!
          if destination &gt; source   {
              var startIndex = source + 1
              let endIndex = destination - 1
              var startOrder = vm.savedEntities[source].order
              while startIndex &lt;= endIndex {
                  vm.savedEntities[startIndex].order = startOrder
                  startOrder = startOrder + 1
                  startIndex = startIndex + 1
              }
              vm.savedEntities[source].order = startOrder
          }
          
          else if destination &lt; source {
              var startIndex = destination
              let endIndex = source - 1
              var startOrder = vm.savedEntities[destination].order + 1
              let newOrder = vm.savedEntities[destination].order
              while startIndex &lt;= endIndex {
                  vm.savedEntities[startIndex].order = startOrder
                  startOrder = startOrder + 1
                  startIndex = startIndex + 1
              }
              vm.savedEntities[source].order = newOrder
          }
          vm.savedEntities[source].circuit = false
          vm.saveData()
          loadNums()
      }
  }
  </code></pre>
  <p>This is the EditWorkouts file that the WorkoutPopUp file connects to:</p>
  <pre><code>struct EditWorkouts: View {
      @EnvironmentObject var workoutList: CoreDataViewModel 
      @StateObject var vm = CoreDataViewModel()  
      @EnvironmentObject var listViewModel: ListViewModel
      let entity: FruitEntity
      //too many @State vars to post
  
      var body: some View {
          
          VStack{
              HStack{
                  //many lines of code for options that alter the respective workout on the list. All are followed by their version of:
                 //.onChange(of:
                 //vm.savedEntities[Int(entity.order)].multiLimb) { _ in
                 //vm.saveData()
                 //loadNums()&quot;
                 //}
                 //-or-
                 //.onChange(of:vm.savedEntities[Int(entity.order)].circuit) { _ in
                 //entity.circuit = entity.circuit
                 //vm.saveData()
                 //}
              }
          }
      }
  }
  </code></pre>
  <p>Picture of CoreData FruitEntity:
  <a href="https://i.stack.imgur.com/XXTLM.png" rel="nofollow noreferrer">Image</a></p>
  <p>Thank you again for your time!!</p>