У меня довольно простой UITableView с ровно 20 элементами (размер их инвентаря в игре). Моя пользовательская ячейка таблицы достаточно умна, чтобы отображать текст «SLOT EMPTY» для ячеек, которые представляют слоты инвентаря, которые не содержат элементов. У меня есть рабочее решение, но мне хотелось знать, есть ли лучший способ справиться с этим.Удаление элементов из UITableView (без их удаления)
Предназначенный результат
инвентарный реестр пользователя может выглядеть следующим образом:
Bellybutton fuzz
Petrified weasel snout
Chocolate covered toilet seat
Coupon for a high-five from Chase
SLOT 5 EMPTY
SLOT 6 EMPTY
.
.
.
SLOT 20 EMPTY
Если пользователь удаляет стульчак то список должен выглядеть следующим образом:
Bellybutton fuzz
Petrified weasel snout
Coupon for a high-five from Chase
SLOT 4 EMPTY
SLOT 5 EMPTY
.
.
.
SLOT 20 EMPTY
Примечание что список по-прежнему содержит 20 ячеек после удаления, когда используемые ячейки сдвинуты вверх, чтобы занять три верхних слота инвентаря.
Проблема
Моя первая попытка была использовать, чтобы использовать [tableView deleteRowsAtIndexPaths:withRowAnimation:]
и корректировать свои данные аккомпанемента, чтобы отразить новое содержание (один меньше предмет инвентаря, один дополнительный пустой слот.) Тем не менее, это разбился с следующее исключение: (?)
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Invalid update: invalid number of rows in section 0. The number of rows
contained in an existing section after the update (20) must be equal to the number
of rows contained in that section before the update (20), plus or minus the number
of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or
minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
раствор
[Обратите внимание, что код в го раздел упрощен от фактического кода для ясности - вопрос о методе решения, а не о конкретных деталях реализации.]
В конце концов я пришел в себя, чтобы немного взломать, но делает привести к предполагаемому результату.
Удаление элемента выглядит следующим образом:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
NSDictionary *item = [self itemForRowAtIndexPath:indexPath];
if (!item) return;
// Keep track of the deleted item count
self.mDeletedEntries += 1;
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
[tableView endUpdates];
// Remove it from the data store
[Inventory removeInventoryItem:item];
}
}
Позже я заменить недостающие элементы:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// If we have deleted some entries and need to add some new ones, schedule
// a process to insert them.
//
// *This is what feels like a hack to me*
if (self.mDeletedEntries)
{
[self performSelector:@selector(addEmptySlots:) withObject:tableView afterDelay:0];
}
// Return the current count that IOS wants (inventory size minus the deleted ones)
return kUserMaxInventorySize - self.mDeletedEntries;
}
- (void)addEmptySlots:(UITableView *)tableView
{
// We start adding entries into the list at the end
int insertLocation = kUserMaxInventorySize - self.mDeletedEntries;
[tableView beginUpdates];
// Add the deleted entries (should only ever be 1 entry, really)
for (int i = 0; i < self.mDeletedEntries; ++i)
{
// They get added to the end of the table
NSIndexPath *path = [NSIndexPath indexPathForRow:insertLocation + i inSection:0];
NSArray *indexArray = [NSArray arrayWithObjects:path,nil];
// Insert the entry. We don't need to actually add the item to our data store,
// since empty entries will simply report "Slot empty" text.
[tableView insertRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationBottom];
}
// These are no longer deleted
self.mDeletedEntries = 0;
[tableView endUpdates];
}
Это работает, но это лучший способ для достижения этой цели?
Я думаю, что я бы просто обновить данные аккомпанемента стола и reloadData - не заморачиваться с стиранием клетки. –
Как насчет простого NSMutableArray с 20 объектами NSString, содержащими 'SLOT% d EMPTY' изначально, а затем начать замену объектов на реальные объекты. При удалении замените его на строку. –
@HotLicks Проблема с reloadData заключается в том, что вы теряете возможность анимировать элемент в списке. У меня было много других проблем с этим, в том числе некоторые ЧРЕЗВЫЧАЙНЫЕ нечетные результаты от ячеек, перемещающихся в верхнюю часть таблицы, и запуск подпрыгивающей анимации позади ячейки, которая уже была наверху. Очень странно. – pauln