【问题标题】:Performance issue : Removing A LOT of cells from a UITableView性能问题:从 UITableView 中删除很多单元格
【发布时间】:2012-08-04 06:26:18
【问题描述】:

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

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

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 删除)。'

有人遇到过这样的性能问题吗?解决方法? 干杯, 光盘

【问题讨论】:

    标签: performance ipad uitableview rowdeleting


    【解决方案1】:

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

    //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。

    【讨论】:

    • 嗨,谢谢!你让我从 150 毫秒下降到 100 毫秒。尽管如此,我还是将 NSLog 检查点分解为计时,发现执行删除的方法是花费时间(500 毫秒): [self.myTableViewController.tableView deleteRowsAtIndexPaths:rowsToDelete withRowAnimation:UITableViewRowAnimationRight];虽然阵列只占总时间的 20%。问题是我正在删除看不见的行,但必须这样做以避免行:insection:异常。知道如何加快删除速度或避免这样做(更改数据源?)-
    • 对不起,我不知道。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      我同意@futureelite7 的观点,即您应该重新加载数据源而不是操纵视图。我对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...
      }
      

      【讨论】:

        猜你喜欢
        • 2017-05-24
        • 1970-01-01
        • 2011-08-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多