Implementing iOS 11 Drag and Drop in a table view. If I don't want the first row to be dragged, I assume I return an empty array from tableView(:itemsForBeginning:)
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
if indexPath.row == 0 {
return []
}
let dragItems = self.dragItems(forRowAt: indexPath)
print("dragging row index \(String(describing: dragItems.first?.localObject as? Int))")
return dragItems
}
Return an empty array when you do not allow the user to drag content from the specified index path.
But even when it's verified that [ ] is returned, the drag still happens. That means either I screwed up or the feature is not implemented as documented. I'm always hesitant to think it's someone else, so my question is if the return of [ ] as implemented should in fact prevent the drag of the 0 row? Anyone else verify this or show it as working as documented?
Thanks
Edit: Sample code from WWDC video includes this chunk:
if tableView.isEditing {
// User wants to reorder a row, don't return any drag items. The table view will allow a drag to begin for reordering only.
return []
}
Is this saying that if you don't return any drag items, the table view will still allow dragging?!?! Then how would one prevent a row from being dragged at all?
Thanks to @Losiowaty for pointing in useful direction.
I knew that in tableView, the drop delegate would look to
tableView(:moveRowAt:)
if there was just oneUIDragItem
. What I didn't see documented anywhere was that it also checked withtableView(:canMoveRowAt:)
, though that now seems obvious in retrospect.My
canMoveRowAt
looked like this:Note the comment inside the method. I don't know if I wrote the comment or copied it from somewhere. I'd prevented row 0 from being editable (deletable and reorder-able in edit mode) and let that override
canMoveRowAt
, but that is ignored with iOS 11 drag and drop apparently. So the solution is to be explicit, as in:An additional complexity in diagnosing this is that the same code in an iMessage app on iPad is not reaching
tableView(:moveRowAt:)
, but is reaching there on iPhone. For an iOS app,tableView(:moveRowAt:)
is reached on both iPad and iPhone, though this may be separate issue.