Одновременная вставка и удаление UITableViewCell не работает

У меня довольно много боли при вставке и удалении 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 http://www.freeimagehosting.net/uploads/1b9f2d57e7.png

Изображение здесь: http://www.freeimagehosting.net/uploads/1b9f2d57e7.png

После выбора строки таблицы 0 раздела 2, я затем удаляю строки раздела 1 (который выбран по умолчанию) и добавляю строки раздела 2. Но я получаю следующее:

http://www.freeimagehosting.net/uploads/6d5d904e84.png http://www.freeimagehosting.net/uploads/6d5d904e84.png

Изображение здесь: http://www.freeimagehosting.net/uploads/6d5d904e84.png

... чего я не ожидал! Похоже, что первая строка раздела 2 каким-то образом осталась - хотя ее окончательно удалили.

Если я просто сделаю [tableView reloadData], все будет выглядеть нормально ... но я, очевидно, предпочитаю красивую анимацию.

Я был бы очень признателен, если бы кто-нибудь мог пролить здесь свет! Это сводит меня с ума!

Еще раз спасибо, Ник.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
7
0
8 315
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

В опубликованном вами коде индекс цикла изменяется от 0 до 4, что предполагает удаление все строк в разделе 1, а затем добавление пяти новых строк в раздел 2. Поскольку в каждом разделе уже есть строка 0, это будет добавить в таблицу экземпляр второй раздела 2, строка 0.

Я бы посоветовал запустить цикл от 1 до 4:

for (int i=1; i<5; i++)
{
    // ...
}

Привет, eJames, спасибо за ваш комментарий - действительно верный момент !! На минуту я подумал, что это может решить мою проблему, но у меня все та же проблема. Я думаю, что на самом деле может быть iPhone, но когда вы пытаетесь удалить элементы из одного раздела и одновременно добавить их в другой раздел ...

Nick Cartwright 02.12.2008 01:01

Кажется, я помню, что 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];

Другие вопросы по теме