UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

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 }
 }

2      

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.

2      

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.

2      

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.

2      

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()
    }

3      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

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

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

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.