TableView reloadData vs. beginUpdates & endUpdates
У меня возникла сложная проблема с обновлением моего TableView, я получаю разные результаты, используя разные методы его обновления, позвольте мне объяснить:
Ситуация 1:
Я использую [tbl reloadData];
, где tbl
мой TableView, для обновления TableView - работает по назначению.
Ситуация 2:
Я использую:
[tbl beginUpdates];
[tbl reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationRight];
[tbl endUpdates];
Где tbl
- мой TableView, а indexPaths
- массив, содержащий все индексы, присутствующие в TableView. Теперь массив в порядке, он содержит все правильные indexPaths (двойные и тройные проверены), но по какой-то причине - это не работает должным образом.
Теперь я понимаю, что это проблема XY (где я прошу Y, но моя проблема действительно X, потому что я думаю, что решение Y будет решать X), и это только потому, что я чувствую, что это немного сложно объяснить X (следствие сказанного выше проблемы) простым способом, поэтому я бы скорее воздержался от этого, если это возможно.
Итак, вплоть до моего вопроса: Есть ли разница между двумя способами обновления TableView (за исключением фрагмента анимации, конечно) или я должен подозревать, что проблема лежит в другом месте?
EDIT:
Хорошо, я попытаюсь объяснить, каковы симптомы:
В методе cellForRowAtIndexPath
я добавляю кнопку для каждой ячейки с назначенным тегом, который равен строке indexPath ячейки, например:
btn.tag = indexPath.row;
Причина, по которой я это делаю, заключается в том, что я могу идентифицировать каждую кнопку, поскольку все они называют одну и ту же функцию:
- (void)btnPressed:(id)sender
Когда я обновляю ячейки, потому что некоторые значения в ячейках изменились - ситуация 1 делает все хорошо, ситуация 2, однако, смешивает теги, поэтому при следующей нажатии одной из кнопок они больше не имеют правильные метки.
Смешивание кажется мне случайным, но рандомизация происходит по-разному, в зависимости от того, какие кнопки я нажимаю первым. Надеюсь, это прояснит мою проблему.
Ответы
Ответ 1
Из документации UITableView
beginUpdates
Начните серию вызовов методов, которые вставляют, удаляют или выберите строки и секции ресивера.
Это означает, что вы не должны использовать это, если вы не вставляете, не удаляете и не выбираете. Вы ничего не делаете.
Кроме того, вы должны положить конец beginUpdates
с помощью endUpdates
, а не reloadData
. Документация:
Эта группа методов должна завершиться вызовом endUpdates.
Ответ 2
Первое различие между reloadData
и reloadRowsAtIndexPaths
состоит в том, что при выполнении reloadRowsAtIndexPaths
существует 2 UITableViewCell
объектов, выделенных одновременно для одного и того же indexPath (потому что tableview "смешивается" в новой ячейке). Это иногда не предусмотрено кодом в cellForRowAtIndexPath
. Сюрприз исходит из того факта, что даже если ячейка уже была выделена для определенного идентификатора ячейки, представление таблицы не возвращает вам эту ячейку в dequeueReusableCellWithIdentifier
при вызове reloadRowsAtIndexPaths
, вместо этого он возвращает nil. В противоречии reloadData
повторно использует уже выделенные ячейки.
Второе различие заключается в том, что endUpdates
после reloadRowsAtIndexPaths
прямо вызывает cellForRowAtIndexPath
(если вы установите там точку останова, в трассировке стека отображается endUpdates
), тогда как reloadData
назначает вызовы cellForRowAtIndexPath
в позднее (не отображается в трассировке стека).
Однако вам нужно будет опубликовать немного больше кода, чтобы дать нам понять, что вы там делаете. В принципе, indexPaths новых ячеек идентичны старым и reloadRowsAtIndexPaths
, если вы не удаляете или не вставляете строки.
Ответ 3
Вызов этого метода, если вы хотите, чтобы последующие операции вставки, удаления и выбора (например, cellForRowAtIndexPath: и indexPathsForVisibleRows) были анимированы одновременно.
Я думаю, что это то, что вы хотите. beginUpdates и endUpdates могут изменить UItableview с анимацией.