Kodeco Forums

Video Tutorial: Table Views in iOS Part 6: Moving Rows

Learn how to move and rearrange your table view cells.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/3300-table-views-in-ios/lessons/7

Hey there,

I am struggling to understand the logic behind moving the rows using the moveRowAtIndexPath method. I understand we need to implement this method here, but what I don’t get is the logic used in this exercise.

I understand the three constants at the start and then it falls apart for me.

Could someone please explain from the if sourceSet block what is going on? Thanks so much.

func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
    let sourceSet = iconSets[sourceIndexPath.section]
    let destinationSet = iconSets[destinationIndexPath.section]
    let iconToMove = sourceSet.icons[sourceIndexPath.row]
    
    if sourceSet == destinationSet {
        if destinationIndexPath.row != sourceIndexPath.row {
            swap(&destinationSet.icons[destinationIndexPath.row], &destinationSet.icons[sourceIndexPath.row])
        } else {
            destinationSet.icons.insert(iconToMove, atIndex: destinationIndexPath.row)
            sourceSet.icons.removeAtIndex(sourceIndexPath.row)
        }
    }
}

There still have a bug ! When i move the row to the same location , Than you can see!
fatal error: swapping a location with itself is not supported

I try to fix the bug in this way and it work
if sourceIndexPath == destinationIndexPath { //don't move return }
just write behind the
if destinationSection == sourceSection { swap(&destinationSection.bugs[destinationIndexPath.row], &sourceSection.bugs[sourceIndexPath.row]) }
in
tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath)

What is happening is the code is checking if you are moving a block within the same section. Each section is a separate array.

If you are moving rows within the same section (that is, the if statement is true), then you can simply swap the two elements of the array. For example, if I drag the table row in position 1 to position 3, the code will swap the two elements at those locations.

If you are moving a row to a different section (that is, the if statement is false), then you need to insert the icon into the row of the new section it is being moved to and remove the icon from the array you are moving from. Again, you can’t simply swap because you are in a different table section and dealing with two different arrays.

I think the solution provided is overly complicated. When I programmed a solution I completed the exact same result in two lines:

    let iconToMove = iconSets[fromIndexPath.section].icons.remove(at: fromIndexPath.row)
    iconSets[to.section].icons.insert(iconToMove, at: to.row)

Delete the icon that is being moved from the iconSet[section] and the icons array[row]. When using .remove method it returns the element being removed and store it. Insert that icon into destination section and row. Simple and easy.

Yes, swap is a bug: the semantics of moving a row is deleting it at it’s original index and inserting it at the destination index. Swapping leads to corruption: the view will not match the underlying model. They got lucky on this video…

The solution provided by sedawk worked for me! Thanks sedawk!