BLACK FRIDAY SALE: Save big on all my Swift books and bundles! >>

SOLVED: Move rows in a list is not working

Forums > SwiftUI

Hi everyone!

I was follow this tutorial and everything seems to be working well, the rows move correctly. But every time I leave this View and re-enter, the rows are arranged in the original order.

I don't know if the problem is about how the ForEach sorts the list or if the array comes from CoreData sorting by date.

Any idea? Thanks!

Here's the code:

@Environment(\.managedObjectContext) var viewContext
@ObservedObject var meeting: Meeting

ForEach(meeting.attendeesArray) { topic in
      HStack {
          Text(topic.unwrappedAttendeeName)
      }
  }
  .onDelete { index in
      vm.delete(at: index, meeting: meeting)
  }
  .onMove(perform: move)
func move(from source: IndexSet, to destination: Int) {
    meeting.attendeesArray.move(fromOffsets: source, toOffset: destination)
    viewContext.save()
}

CoreData Meeting entity:

@NSManaged public var title: String?
@NSManaged public var attendees: NSSet?

public var attendeesArray: [Ateendee] {
    let attendeeSet = attendees as? Set<Attendee> ?? []
    return attendeeSet.sorted { $0.attendeeDate < $1.attendeeDate }
 }

   

This is because you don't save the new order. You need an additional property which stores the order. Everytime you sort the order after attendeeDate and the attendeeDate is not changed when you change the order.

   

Hi @Hatsushira, thank you for your answer!

You need an additional property which stores the order

And how is the best way to archived this? Because I have tried assigning a new date to attendeeDate at the time of changing the order but it has not worked. Any ideas?

Again, thanks.

   

You could add an Integer attribute to your entity. Everytime you add a record you can set this value to record count + 1. Then when you move, you have to set the order of the moved object to the new index and you have to set all other orders which are below to currentValue + 1. In your attendeesArray sort after order. When you use attendeeDate you would need to set the date to a value between the record before and the record after to keep the order. Which probably isn't what you want because this attribute stores a specific date and should not be used to keep track of the order.

   

I've finally been able to do it! Thank you very much @Hatsushira!!

I leave the code below in case it can be useful to someone.

I had to update the entity in CoreData with a new "order" attribute:


@NSManaged public var title: String?
@NSManaged public var attendees: NSSet?
@NSManaged public var order: Int16

Then the method updated:


private func move(from source: IndexSet, to destination: Int) {

        var revisedAttendees = meeting.attendeesArray

        revisedAttendees.move(fromOffsets: source, toOffset: destination )

        for reverseIndex in stride( from: revisedAttendees.count - 1, through: 0, by: -1 ) {
            revisedAttendees[ reverseIndex ].order =
                Int16( reverseIndex )
        }
        viewContext.save()
    }

1      

Hacking with Swift is sponsored by RevenueCat

SPONSORED In-app subscriptions are a pain to implement, hard to test, and full of edge cases. RevenueCat makes it straightforward and reliable so you can get back to building your app. Oh, and it's free if your app makes less than $10k/mo.

Learn more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.