UITableView插入行崩溃

时间:2015-08-04 00:33:01

标签: ios uitableview

我有这个委托方法从API返回数据:

- (void)pagedDataSource:(PagedDataSource *)dataSource
 didLoadAdditionalItems:(NSInteger)items; {


    NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:items];
    NSInteger numberOfItems = [dataSource numberOfItems];

    for (int i = (int)numberOfItems - (int)items; i < numberOfItems; ++i) {
        [indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
    }

    [UIView setAnimationsEnabled:NO];
    [[self tableView] beginUpdates];

    [[self tableView] insertRowsAtIndexPaths:indexPaths
                            withRowAnimation:UITableViewRowAnimationNone];

    [[self tableView] endUpdates];
    [UIView setAnimationsEnabled:YES];
}

所以第一次它运行良好但是当我尝试加载新条目然后程序再次调用这个委托方法时,它会导致崩溃。

让我简单描述它是如何运作的。

所以我有PagedDataSource对象,我初始化了一些块,当PagedDataSource从API接收数据时它应该返回请求数据,它将数据推送到我的视图控制器并使用自指针。所以你可以看到上面这个方法。然后在这个方法中,我尝试插入我刚收到的所需行。当我向下滚动表格时,它会请求新项目,每次app在接收新数据后调用此方法时,我会再插入一行。

例如,如果我第一次收到16个项目,那么我会插入0到15之间的行

然后当我向下滚动表格时,我会在16到31之间插入新行。所以假设我的限制=每个请求16个项目。

但问题是我加载一些项目例如144项后,我想用新数据集重新加载我的表。所以我从0开始加载数据。

假设我第一次请求了144个视频,然后点击一个按钮,现在我想看到此表中另一个类别的7个视频。但它导致了这次崩溃,因为这里

- (void)pagedDataSource:(PagedDataSource *)dataSource
     didLoadAdditionalItems:(NSInteger)items;

它尝试从0插入新项目,我遇到了这个问题:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to insert row 144 into section 0, but there are only 0 rows in section 0 after the update'

所以我检查了indexPaths数组的计数,这里第一次只有7项。

我该怎么办?我如何删除或释放表视图?

所以只需跳过所有写入。所以我假设我第一次加载了16个项目

这是我上面描述的indexPaths数组的日志:

<__NSArrayM 0x7fbdc1e8af50>(
<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0},
<NSIndexPath: 0xc000000000008016> {length = 2, path = 0 - 1},
<NSIndexPath: 0xc000000000010016> {length = 2, path = 0 - 2},
<NSIndexPath: 0xc000000000018016> {length = 2, path = 0 - 3},
<NSIndexPath: 0xc000000000020016> {length = 2, path = 0 - 4},
<NSIndexPath: 0xc000000000028016> {length = 2, path = 0 - 5},
<NSIndexPath: 0xc000000000030016> {length = 2, path = 0 - 6},
<NSIndexPath: 0xc000000000038016> {length = 2, path = 0 - 7},
<NSIndexPath: 0xc000000000040016> {length = 2, path = 0 - 8},
<NSIndexPath: 0xc000000000048016> {length = 2, path = 0 - 9},
<NSIndexPath: 0xc000000000050016> {length = 2, path = 0 - 10},
<NSIndexPath: 0xc000000000058016> {length = 2, path = 0 - 11},
<NSIndexPath: 0xc000000000060016> {length = 2, path = 0 - 12},
<NSIndexPath: 0xc000000000068016> {length = 2, path = 0 - 13},
<NSIndexPath: 0xc000000000070016> {length = 2, path = 0 - 14},
<NSIndexPath: 0xc000000000078016> {length = 2, path = 0 - 15}
)

然后我有切换器在同一个表中加载另一个对象然后调用上面描述的方法这里是indexPaths的日志(第二次):

<__NSArrayM 0x7fbdc1e13920>(
<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0},
<NSIndexPath: 0xc000000000008016> {length = 2, path = 0 - 1},
<NSIndexPath: 0xc000000000010016> {length = 2, path = 0 - 2},
<NSIndexPath: 0xc000000000018016> {length = 2, path = 0 - 3},
<NSIndexPath: 0xc000000000020016> {length = 2, path = 0 - 4},
<NSIndexPath: 0xc000000000028016> {length = 2, path = 0 - 5},
<NSIndexPath: 0xc000000000030016> {length = 2, path = 0 - 6}
)

我在[[self tableView] endUpdates];

上获得了SIGABRT

1 个答案:

答案 0 :(得分:1)

我认为您在NSIndexPath专门附加indexPathForRow:i时出错。并确保您的dataSource已更新。

试试这个:

[dataSource addObject:@"boom0"];
[dataSource addObject:@"boom1"];
[dataSource addObject:@"boom3"];
[dataSource addObject:@"boom4"];

NSInteger item = 4;

NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:item];

for (int i = item; i != 0; i--)
{
    [indexPaths addObject:[NSIndexPath indexPathForRow:dataSource.count - i inSection:0]];
}

[tableView beginUpdates];

[tableView insertRowsAtIndexPaths:indexPaths
                        withRowAnimation:UITableViewRowAnimationNone];

[tableView endUpdates];

修改

要重新填充表,您需要做的是从dataSource中删除所有对象,如:

[dataSource removeAllObjects];

重新加载你的表

[tableView reloadData];

诀窍就在你的dataSource中,你应该如何操纵它。

//This is using method

- (void)pagedDataSource:(PagedDataSource *)dataSource didLoadAdditionalItems:(NSInteger)items repopulate:(BOOL)repopulate
{
    if(repopulate)
    {
        [dataSource removeAllObjects];

        [tableView reloadData];
    }

    //this will execute the codes below 

    ...
}

您还可以跟踪部分中的行数: 如果当前计数dataSource小于先前计数

触发removeAllObjects&amp; reloadData

int previousCount = 0;

- (void)pagedDataSource:(PagedDataSource *)dataSource didLoadAdditionalItems:(NSInteger)items
{
    if([dataSource numberOfItems] < previousCount)
    {
        [dataSource removeAllObjects];

        [tableView reloadData];
    }

    //this will execute the codes below 

    ...
}

另一种选择是在dataSource已经更新时重新加载表,因为单元格已经制作好了,我们不需要创建一个新的,或者你想重新制作单元格?嗯..

- (void)pagedDataSource:(PagedDataSource *)dataSource didLoadAdditionalItems:(NSInteger)items
{
    if([dataSource numberOfItems] < previousCount) // || if(repopulate)
    {
        [tableView reloadData];

        return;
    }

    //this will not / must not execute the codes below 

    ...
}

希望这对你有所帮助,干杯...... :)