У меня довольно много боли при вставке и удалении UITableViewCells из того же UITableView!
Обычно я не публикую код, но я подумал, что это лучший способ показать, где у меня проблема:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 5;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (iSelectedSection == section) return 5;
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//NSLog(@"drawing row:%d section:%d", [indexPath row], [indexPath section]);
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
if (iSelectedSection == [indexPath section]) {
cell.textColor = [UIColor redColor];
} else {
cell.textColor = [UIColor blackColor];
}
cell.text = [NSString stringWithFormat:@"Section: %d Row: %d", [indexPath section], [indexPath row]];
// Set up the cell
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic -- create and push a new view controller
if ([indexPath row] == 0) {
NSMutableArray *rowsToRemove = [NSMutableArray array];
NSMutableArray *rowsToAdd = [NSMutableArray array];
for(int i=0; i<5; i++) {
//NSLog(@"Adding row:%d section:%d ", i, [indexPath section]);
//NSLog(@"Removing row:%d section:%d ", i, iSelectedSection);
[rowsToAdd addObject:[NSIndexPath indexPathForRow:i inSection:[indexPath section]]];
[rowsToRemove addObject:[NSIndexPath indexPathForRow:i inSection:iSelectedSection]];
}
iSelectedSection = [indexPath section];
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:rowsToRemove withRowAnimation:YES];
[tableView insertRowsAtIndexPaths:rowsToAdd withRowAnimation:YES];
[tableView endUpdates];
}
}
Этот код создает 5 разделов, 1-й (индексированный с 0) с 5 строками. Когда вы выбираете раздел - он удаляет строки из раздела, который вы ранее выбрали, и добавляет строки в только что выбранный раздел.
Наглядно, когда я загружаю приложение, у меня получается что-то вроде этого:
Изображение здесь: http://www.freeimagehosting.net/uploads/1b9f2d57e7.png
После выбора строки таблицы 0 раздела 2, я затем удаляю строки раздела 1 (который выбран по умолчанию) и добавляю строки раздела 2. Но я получаю следующее:
Изображение здесь: http://www.freeimagehosting.net/uploads/6d5d904e84.png
... чего я не ожидал! Похоже, что первая строка раздела 2 каким-то образом осталась - хотя ее окончательно удалили.
Если я просто сделаю [tableView reloadData], все будет выглядеть нормально ... но я, очевидно, предпочитаю красивую анимацию.
Я был бы очень признателен, если бы кто-нибудь мог пролить здесь свет! Это сводит меня с ума!
Еще раз спасибо, Ник.





В опубликованном вами коде индекс цикла изменяется от 0 до 4, что предполагает удаление все строк в разделе 1, а затем добавление пяти новых строк в раздел 2. Поскольку в каждом разделе уже есть строка 0, это будет добавить в таблицу экземпляр второй раздела 2, строка 0.
Я бы посоветовал запустить цикл от 1 до 4:
for (int i=1; i<5; i++)
{
// ...
}Кажется, я помню, что numberOfRowsInSection: будет вызываться при вызове deleteRows или insertRow, вам нужно быть очень осторожным, чтобы cliams numberOfRowsInSection соответствовал вашим изменениям. В этом случае вы можете попробовать переместить iSelectedSection = [indexPath section]; строка после endUpdates.
Я не помню, где я это читал, но я считаю, что вам не следует выполнять обновления строк таблицы (вставки и удаления) изнутри одной из функций делегата табличного представления. Я думаю, что лучшей альтернативой было бы выполнение выполненияSelectorOnMainThread, передающее необходимую информацию, необходимую для выполнения обновлений как объекта. Что-то типа:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// ....
[self performSelectorOnMainThread: @selector(insertRows:)
withObject: someObjectOrNil]; // double check args
}
- (void) insertRows: (NSObject*)someObjectOrNil {
[tableView beginUpdates];
// update logic
[tableView endUpdates];
// don't call reloadData here, but ensure that data returned from the
// table view delegate functions are in sync
}
К вашему сведению: эта ошибка, похоже, была полностью исправлена с обновлением iPhone 2.2. Спасибо, Apple! Ник.
Пытался заставить это работать. Вот мой код для добавления строки в мой tableView:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[tableView beginUpdates];
[dataSource insertObject:[artistField text] atIndex:0];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
[tableView endUpdates];
Привет, eJames, спасибо за ваш комментарий - действительно верный момент !! На минуту я подумал, что это может решить мою проблему, но у меня все та же проблема. Я думаю, что на самом деле может быть iPhone, но когда вы пытаетесь удалить элементы из одного раздела и одновременно добавить их в другой раздел ...