性能问题:从UITableView中删除大量单元格

时间:2010-12-15 20:48:56

标签: performance ipad uitableview rowdeleting

我有一个超过1000个单元格的表格视图(我在屏幕上显示大约10个)。在用户执行“过滤”操作之后,我想删除大约80%的用户,然后在第二次过滤后另外80%。当使用100个单元时,它大致是瞬间的,但是1000只需要0.5秒才能完成方法[tableView endUpdates],这完全破坏了用户体验。

我创建了像这样的索引路径数组:

for (int i=1; i<[appDelegate.myArray count]; i++) {   //more than 1000 objects in myArray
    if (![[appDelegate.myArray objectAtIndex:i] myTest]) {  //myTest returns a BOOL 
        [appDelegate.rowsToDelete addObject:[NSIndexPath xxxxx]]; //the index path of the object that just failed the test and must be removed];
 }
}
[self.myTableViewController.tableView deleteRowsAtIndexPaths:appDelegate.rowsToDelete withRowAnimation:UITableViewRowAnimationRight];

我尝试了2个解决方案,其中一个是线程化,这样我的用户就可以看到UI的其他部分正在移动,而tableView正在更新。但如果他启动另一级别的过滤,这通常会导致漫长的等待,如果不是崩溃。

我还尝试删除前几个单元格(屏幕上的那些单元格),然后从数据源中删除其他未通过测试的对象,而不从tableView中移除相应的单元格,因为它们看不见。这给出了良好,快速的结果,但是我遇到了行数问题,例如:

'无效更新:第0节中的行数无效。更新后现有部分中包含的行数(94)必须等于更新前该部分中包含的行数(927)加上或减去从该部分插入或删除的行数(插入0,删除215)。'

有人有这样的性能问题吗?解决方法? 干杯, CD

3 个答案:

答案 0 :(得分:0)

尝试缓存属性并对循环使用快速枚举:

//int i = 0;
NSMutableArray *rowsToDelete = appDelegate.rowsToDelete;
for(id current in appDelegate.myArray) {
    if([current myTest]) [rowsToDelete addObject:[NSIndexPath ...]];
    //++i;
}
[self.myTableViewController.tableView deleteRowsAtIndexPaths:rowsToDelete withRowAnimation:UITableViewRowAnimationRight];

如果使用项目的索引创建NSIndexPath,请取消注释第一行和第五行。另外,我注意到你的代码中你从i = 1开始。由于NSArrays从0开始,因此永远不会删除第一个单元格。如果您确实想要这个,请将i = 0更改为i = 1.

答案 1 :(得分:0)

您可能只想使用新的行数进行过滤并重新加载整个表视图。如果最终看不到它们,那么完成所有这些删除动画是没有意义的。或者只是确定哪个部分可见,然后仅加载和删除用户当前可见的那些行?

答案 2 :(得分:0)

我同意@ futureelite7你应该重新加载dataSource而不是操纵视图。我提出了similar question here的解决方案。

基本思想是调用reloadSections:withRowAnimation:并在你的UITableViewDataSource方法中切换分段控件的selectedSegmentIndex。

假设您的数据是平的(只有一个部分),它看起来像这样:

- (IBAction)segmentSwitch:(id)sender
{
    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    switch (self.segmentedControl.selectedSegmentIndex)
    {
        default:
        case 0:
            return [self.allRows count];
        case 1:
            return [self.onlySomeRows count];
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    id data;
    switch (self.segmentedControl.selectedSegmentIndex)
    {
        default:
        case 0:
            data = [self.allRows objectAtIndex:[indexPath row]];
            break;
        case 1:
            data = [self.onlySomeRows objectAtIndex:[indexPath row]];
            break;
    }

    //TODO: use data to populate and return a UITableViewCell...
}