Перекрестная публикация моего ответа на этот связанный вопрос :
Я просто столкнулся с той же проблемой в моем приложении.
Ситуация такова, что у меня есть два раздела таблицы. Элементы можно перетаскивать внутри и между разделами. Пользователи могут перетаскивать ячейки в любую строку в первом разделе, но во втором разделе элементы сортируются, поэтому для любой данной ячейки есть только одна действительная строка.
Если я прокручиваю вид так, чтобы нижняя часть секции 1 и верхняя часть секции 2 были видны, возьмите элемент в секции 1, который сортируется по нижней части секции 2, и перетащите его в верхнюю часть секции 2, Мой tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:
метод вызывается, и я возвращаю правильную позицию назначения, которая находится на несколько строк ниже нижней части экрана. В пользовательском интерфейсе вы можете увидеть пустую ячейку, созданную в нижней части экрана, которая не является правильной строкой назначения.
Когда вы отпустите ячейку, та поддельная ячейка, которая была создана в нижней части экрана (в середине раздела 2), останется там! tableView:cellForRowAtIndexPath:
никогда даже не вызывается за это. Как только вы пытаетесь что-то сделать с этой камерой, вы терпите крах.
Моим первым решением было просто вызвать [tableView reloadData] в конце tableView:moveRowAtIndexPath:toIndexPath:
. Но это вызывает сбой, поэтому вместо задержки я вызываю его косвенно. Но есть еще одна ошибка: после отложенного вызова reloadData, tableView:moveRowAtIndexPath:toIndexPath:
снова вызывается с поддельным запросом, чтобы переместить элемент на один конец конца первого раздела в ту же позицию. Поэтому мне пришлось добавить код, чтобы игнорировать фиктивные запросы на запрет операций.
Итак, вот код:
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)pathSrc toIndexPath:(NSIndexPath *)pathDst
{
// APPLE_BUG: after doing the delayed table reload (see below), we get a bogus
// request to move a nonexistant cell to its current location
if (pathSrc.row == pathDst.row && pathSrc.section == pathDst.section)
return;
// update your data model to reflect the move...
// APPLE_BUG: if you move a cell to a row that's off-screen (because the destination
// has been modified), the bogus cell gets created and eventually will cause a crash
[self performSelector:@selector(delayedReloadData:) withObject:tableView afterDelay:0];
}
- (void)delayedReloadData:(UITableView *)tableView
{
Assert(tableView == self.tableView);
[tableView reloadData];
}
Обратите внимание, что все еще есть ошибка пользовательского интерфейса. На экране перетаскиваемая ячейка анимируется в поддельную пустую ячейку. В конце анимации пустая ячейка перерисовывается с правильными данными для этой строки, но наблюдающий пользователь заметит, что перетаскиваемая ячейка оживляется в неправильное место, а затем мгновенно преобразуется в другую ячейку.
Это определенно глупый пользовательский интерфейс. Я подумал о прокрутке нужной строки назначения на экране, но если бы я сделал это, она бы заполнила экран вторым разделом, и любая попытка перетаскивания назад к первому разделу будет постоянно срываться моей (теперь раздражающей) автоматической прокруткой. Возможно, мне придется изменить пользовательский интерфейс, но для этого потребуются некоторые сложные и надоедливые изменения в моей модели данных.