Проблемы с одновременной вставкой / удалением строк в UITableView - PullRequest
0 голосов
/ 22 ноября 2011

Я боролся с этой проблемой уже пару дней.Мне нужно одновременно удалить и вставить несколько строк в UITableView внутри блока beginUpdates / endUpdates, но некоторые из вставленных строк имеют индекс, который превосходит исходное количество элементов табличного представления.Я взял пример кода из документации Apple по пакетной вставке и удалению и изменил его, чтобы вызвать ту же проблему, вот код:

#import "MasterViewController.h"

@implementation MasterViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        self.title = NSLocalizedString(@"Master", @"Master");
        states = [[NSMutableArray arrayWithObjects:@"Arizona", @"California", @"New Jersey", @"Washington", nil] retain];
    }
    return self;
}

- (void)dealloc
{
    [states release];
    [super dealloc];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [states count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }

    cell.textLabel.text = [states objectAtIndex:indexPath.row];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [states removeObjectAtIndex:0];
    [states removeObjectAtIndex:0];
    [states removeObjectAtIndex:0];

    [states insertObject:@"Alaska" atIndex:1];
    [states insertObject:@"Georgia" atIndex:1];
    [states insertObject:@"Wisconsin" atIndex:1];

    NSArray *deleteIndexPaths = [NSArray arrayWithObjects:
                             [NSIndexPath indexPathForRow:0 inSection:0],
                             [NSIndexPath indexPathForRow:1 inSection:0],
                             [NSIndexPath indexPathForRow:2 inSection:0],
                             nil];

    NSArray *insertIndexPaths = [NSArray arrayWithObjects:
                             [NSIndexPath indexPathForRow:2 inSection:0],
                             [NSIndexPath indexPathForRow:3 inSection:0],
                             [NSIndexPath indexPathForRow:4 inSection:0],
                             nil];

    UITableView *tv = (UITableView *)self.view;

    [tv beginUpdates];
    [tv insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationTop];
    [tv deleteRowsAtIndexPaths:deleteIndexPaths withRowAnimation:UITableViewRowAnimationTop];
    [tv endUpdates];
}

@end

Когда я запускаю это и нажимаю на любую строку, я получаю следующееисключение:

*** Assertion failure in -[_UITableViewUpdateSupport _computeRowUpdates], /SourceCache/UIKit_Sim/UIKit-1912.3/UITableViewSupport.m:386
Uncaught exception: Invalid table view update.  The application has requested an update to the table view that is inconsistent with the state provided by the data source.

Что-то в корне не так с этим кодом, которого я не вижу?

Ответы [ 2 ]

11 голосов
/ 22 ноября 2011

В документации для insertRowsAtIndexPaths:withRowAnimation: четко указано, что удаление происходит до вставки в блок обновления:

Обратите внимание на поведение этого метода, когда он вызывается в анимационном блоке, определенном методами beginUpdates и endUpdates. UITableView откладывает любые вставки строк или разделов до тех пор, пока он не обработает удаление строк или разделов. Это происходит независимо от порядка вызовов методов вставки и удаления.

Подробнее в Руководстве по программированию табличного представления:

Однако это не тот порядок, в котором UITableView завершает операции. Он откладывает любые вставки строк или разделов до тех пор, пока не обработает удаление строк или разделов. Табличное представление ведет себя так же, как и методы повторной загрузки, вызываемые внутри блока обновления - перезагрузка происходит по отношению к индексам строк и разделов перед выполнением блока анимации. Это происходит независимо от порядка вызовов методов вставки, удаления и перезагрузки.

Операции удаления и перезагрузки в блоке анимации указывают, какие строки и разделы в исходной таблице следует удалить или перезагрузить; вставки указывают, какие строки и разделы должны быть добавлены в итоговую таблицу. Индексные пути, используемые для идентификации разделов и строк, следуют этой модели. С другой стороны, вставка или удаление элемента в непостоянном массиве может повлиять на индекс массива, используемый для последовательной операции вставки или удаления; например, если вы вставляете элемент с определенным индексом, индексы всех последующих элементов в массиве увеличиваются.

0 голосов
/ 11 сентября 2014

В этом случае вам не нужно вставлять или удалять строки, технически totalAddedRows = добавлениеRows-deleteRows (здесь 3-3 = 0), так что просто обновите строки или перезагрузите таблицу, данные автоматически изменятся.

Если totalAddedRows равно + ve, вставьте новые строки, а если оно отрицательное, удалите строки. Не добавляйте и не удаляйте одновременно.

Примечание: Ваше приложение получает сбой, потому что если вы вызываете insert Row, то общее количество массивов составляет только 3.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...