SwiftUI List “stutter” when moving rows, trigger by Core Data save to update orderNum

When moving a row in a SwiftUI List I note that due to my "save Core Data" call the UI transition is jerky. I call save against core data as the list items orderNum has changed, so I'm saving that change that. Video and code below. If I remove the "GCCoreData.save()" there is no stutter.


Animated GIF: https://i.stack.imgur.com/lsmtV.gif


Code - Extract from my SwiftUI View


    private var tasksFetchRequest : FetchRequest
    private var gcTasks : FetchedResults { tasksFetchRequest.wrappedValue }
    init(withGcList gcList:GCList) {
        self.currentList = gcList
        self.tasksFetchRequest = FetchRequest(
            entity: GCTask.entity(),
            sortDescriptors: [NSSortDescriptor(key: "orderNum", ascending: true)],
            predicate: NSPredicate(format: "gcList == %@", currentList)
        )
    }
        private func updateOrderNums(startIndex: Int, destIndex: Int, inc: Int) {
            var currIndex = startIndex
            while currIndex <= destIndex {
                gcTasks[currIndex].orderNum = gcTasks[currIndex].orderNum + Int64(inc)
                currIndex += 1
            }
        }
       
        fileprivate func moveRow(fromStartIndex taskStartIndex: IndexSet.Element, toDestIndex taskDestIndex: Int, movingDown moveDown: Bool) {
            gcTasks[taskStartIndex].orderNum = gcTasks[taskDestIndex].orderNum
            updateOrderNums(
                startIndex: moveDown ? taskStartIndex + 1 : taskDestIndex,
                destIndex: moveDown ? taskDestIndex : taskStartIndex - 1,
                inc: moveDown ? -1 : 1
            )
          
            // Save
            GCCoreData.save() // <<== JERKINESS OCCURS DUE TO THIS
        }



Code - Library functions called


  class GCCoreData: NSObject {
   
        static func save() {
            let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
            if context.hasChanges {
                do {
                    try context.save()
                } catch {
                    let nserror = error as NSError
                    fatalError("Unresolved error performing Core Data save: \(nserror), \(nserror.userInfo)")
                }
            }
        }
      
    }


Note that change the "GCCoreData.save()" line to the below also does not assist.


        DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
            GCCoreData.save()
        }







[1]: https://i.stack.imgur.com/lsmtV.gif

Replies

According to this SO post, you need to add a UUID to each list item: https://stackoverflow.com/questions/61571422/unwanted-animation-when-moving-items-in-swiftui-list. Seems like an odd bug, especially since there is already an ID used in the ForEach.