0

I'll keep it simple, I have a List with UUID identified items. This list is selectable, when EditMode() is entered user can tap items, and these get added to the selection variable:

Selectable list

And the selection variable is:

@State var selection = Set<UUID?>()

However, the issue is that I care about the order in which the items are selected. And in the selection array, the items are not updated in a FIFO or LIFO way, they seem to be random or perhaps it depends on the value of the UUID but the point is it doesn't conserve the order in which they are added.

I considered using a stack to keep track of what is added, but the List + selection combination in SwiftUI doesn't appear to have built in methods to inform of new additions e.g. UUID 1234 has been added. I can thing of "not clean" ways to make it work like iterating through the whole selection Set every time selection.count changes and add the "new item" to the stack but I wouldn't want to come down to that.

sgtpotatoe
  • 340
  • 6
  • 17
  • 1
    A `Set` is unordered by definition. Swift doesn't provide a native ordered set (a set with a backing array) but you might find something [here](https://stackoverflow.com/questions/46534269/swift-ordered-set). By the way, why is UUID optional? – vadian May 10 '21 at 16:39
  • For no good reason, when I created the entity and gave it a UUID field it defaulted to UUID? when I created the NSManaged subclass, might change it if it's problematic – sgtpotatoe May 10 '21 at 19:12
  • I will try playing around with OrderedSets see if there is any luck, thanks! Haven't used Sets often and forgot they are unordered by definition – sgtpotatoe May 10 '21 at 19:15

1 Answers1

1

So after some research, the List constructor that enables selection in .editMode does specify that the selection variable has to be a Set and nothing but a Set:

public init(selection: Binding<Set<SelectionValue>>?, @ViewBuilder content: () -> Content)

So I decided to implement my own array that keeps track of the selection order. I'll show how in case it helps anyone, but it is quite rudimentary:

     @State var selectedItemsArray=[UUID]()
     ...
     List(selection: $selection) {
     ...
     }
     .onChange(of: selection) { newValue in
        if newValue.count>selectedItemsArray.count {
          for uuid in newValue {
            if !selectedItemsArray.contains(uuid) {
                selectedItemsArray.append(uuid)
                break
            }
          }
        }
        if newValue.count<selectedItemsArray.count {
          for uuid in selectedItemsArray {
            if !newValue.contains(uuid) {
                selectedItemsArray.remove(at:  selectedItemsArray.firstIndex(of: uuid)!)
                 break
              }
           }
        }
     }
sgtpotatoe
  • 340
  • 6
  • 17