SwiftReorder icon indicating copy to clipboard operation
SwiftReorder copied to clipboard

Reordering to top is broken on iOS 13.3, Xcode 11.3.1

Open anton-plebanovich opened this issue 4 years ago • 12 comments

So spend half a day today trying to figure out and maybe fix a bug with cell reordering when you try to reorder a cell to the top with a scrolling involved. Basically all you need to do is to scroll at least a little bit down and then try to reorder cell to the very top. There'll be an animation glitch on the last cell reordering. It especially obvious for grouped table views. I used iPhone SE for tests.

1

I tried to force layout first and contentOffset restore after to prevent jumps but while I almost fixed a jump glitch cells content and sizes started to glitch so no idea how to fix this one.

anton-plebanovich avatar Jan 18 '20 17:01 anton-plebanovich

Well at least found a workaround for now - just do not animate last cell move. In ReorderController+DestinationRow.swift updateDestinationRow() use this:

        if #available(iOS 13.0, *), newContext.destinationRow == IndexPath(row: 0, section: 0) {
            tableView.reloadData()
        } else {
            tableView.moveRow(at: context.destinationRow, to: newContext.destinationRow)
        }

Not sure, though, about the concrete iOS 13 version this bug was introduced.

anton-plebanovich avatar Jan 18 '20 17:01 anton-plebanovich

Reproduces on iOS 13.2.2 and iOS 13.3

anton-plebanovich avatar Jan 18 '20 18:01 anton-plebanovich

I am running into this issue as well & added the fix you provided but it created a new issue where it makes all other cells I scroll over invisible. Do you know what might be causing that? Thank you

BrentonBeltrami avatar Jan 31 '20 20:01 BrentonBeltrami

@dontKnowWhatIAmDoin try to replace original lines:

        tableView.beginUpdates()
        tableView.deleteRows(at: [context.destinationRow], with: .fade)
        tableView.insertRows(at: [newContext.destinationRow], with: .fade)
        tableView.endUpdates()

with those:

        if #available(iOS 13.0, *), newContext.destinationRow == IndexPath(row: 0, section: 0) {
            tableView.reloadData()
        } else {
            tableView.beginUpdates()
            tableView.deleteRows(at: [context.destinationRow], with: .fade)
            tableView.insertRows(at: [newContext.destinationRow], with: .fade)
            tableView.endUpdates()
        }

Overall, thise fix shouldn't affect anything except reordering to the first row.

anton-plebanovich avatar Feb 01 '20 11:02 anton-plebanovich

Thank you, this worked for me.

BrentonBeltrami avatar Feb 01 '20 18:02 BrentonBeltrami

@anton-plebanovich That works great, thanks :D

Ant-Adis avatar Apr 30 '20 11:04 Ant-Adis

@anton-plebanovich , why not just tableView.moveRow(at: sourceIndexPath, to: destinationIndexPath)?

andreigubceac avatar Apr 30 '20 12:04 andreigubceac

@andreigubceac I am not the author so can't be sure, just left that as is.

anton-plebanovich avatar May 01 '20 13:05 anton-plebanovich

@anton-plebanovich It's not working anymore (iOS 13.6) even when using the fixes here. Does anyone have any updated workaround?

DantePuglisi avatar Aug 31 '20 17:08 DantePuglisi

have the same issue , and this workaround does not fix the issue

Saulenco avatar Sep 09 '20 10:09 Saulenco

have the same issue, is it fix?

mohdtahir-kiwi avatar Apr 01 '21 14:04 mohdtahir-kiwi

Hi guys found an alternative. Check full answer here

tableView.dragInteractionEnabled = true
tableView.dragDelegate = self
tableView.dropDelegate = self

func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { }

extension TableView: UITableViewDragDelegate {
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
        return [UIDragItem(itemProvider: NSItemProvider())]
    }
} 

extension TableView: UITableViewDropDelegate {
    func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal {

        if session.localDragSession != nil { // Drag originated from the same app.
            return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
        }

        return UITableViewDropProposal(operation: .cancel, intent: .unspecified)
    }

    func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
    }
}

Saulenco avatar May 26 '21 09:05 Saulenco