Timing issue with SwiftUI/SwiftData autosave

I have an issue that is a timing issue.

The issue is I have a list:

    List(sidebars[0].childrenSorted!, id:\.id, children: \.childrenSorted, selection: $selected) { sidebar in

It works great for me., as is.

I am now implementing add, delete, and move (drag and drop) functionality to the list.

The data is persisted in SwiftData, so the order of the array is not maintained, and I have a field called "index," which allows it to be sorted correctly for each display. That also works.

If I insert or move an item in the list, I must update the index of all the elements after the insertion point in that "child" (folder) to the new order/sequence number.

Here is the code for dropping a row item onto another row item in the same child/folder. (Note: indexes are incremented by 2 to allow for the insertion of new items and reindexing) The dropped item should be placed after the target item:

    func dropOnSidebarItem(dropped: Sidebar, target: Sidebar) {
        if target.parent_?.id != dropped.parent_?.id { // moving to new parent
            dropped.parent_?.children_?.removeAll(where: {$0.id == dropped.id})
            dropped.parent_ = target.parent_
            target.parent_?.children_?.append(dropped)
        }
        dropped.index = target.index + 1
        
        var ix = 0
        target.parent_?.childrenSorted?.forEach { child in
            child.index = ix
            ix += 2
        }
    }

If I run this as is, it will crash at the List statement with a nil access to the sidebars[0].

If I add this after the reindexing loop (above), it runs correctly:

        target.parent_?.childrenSorted?.forEach { child in
            print("\(child.title)")
        }

All this addition does is to put a slight delay before returning. That is an obvious HACK doomed to failure at some point.

The issue appears to be that the list is updated before the reindexing is complete.

I have tried placing the reindexing into a function with a tempModelContext that does not autosave. I then manually save the temporary context once the loop is done - the same failure occurs, and the same "delay" makes it work.

Do you have any suggestions on what I am doing wrong? It appears to be associated with autosaving the SwiftData changes.

TIA,

Frank

If I take out the reindexing loop, it works fine, except, of course, the position isn't always right when its index collides with another one.

Timing issue with SwiftUI/SwiftData autosave
 
 
Q