2011-05-03 33 views
0

我的应用程序的UI类似于Phone.app-> Latest:UITableView和导航栏中的UISegmentedControl。我想要做的是在选择第一部分的情况下显示全套数据,如果选择了第二部分,则显示过滤的数据集。过滤分段UITableView

当用户选择UISegmentedControl中的第二项时,我从表视图中删除特定的行。这里是代码:

[tableView beginUpdates]; 
NSMutableArray *indexPaths = [NSMutableArray array]; 
/// ... fill up indexPaths with row indexes 
[tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade]; 
[tableView endUpdates]; 

上面的代码工作正常,除了一个严重的问题:性能。删除2200行中的1500个大约需要20秒。这显然是不可接受的。用动画过滤表格视图行的最佳方法是什么?

回答

1

对于大的变化,以您的数据源,所以建议您使用

[tableView reloadData] 

,而不是

[tableView beginUpdates]; 
// changes here .... 
[tableView endUpdates]; 

编辑:我还没有尝试过这种方法我自己,但考虑改变只有那些包含在可见单元集合中的​​行,可能是上面和下面的缓冲区。你可以通过调用

[tableView indexPathsForVisibleRows]; 
+0

iOS SDK文档是否指定了建议的最大值在beginUpdates和endUpdates之间删除/插入的行是否保持动画顺畅? – sgosha 2011-05-03 19:56:04

+0

不是我知道关闭,但reloadData只关注表视图中的可见单元格,这使得它更快。我相信你可以尝试确切的数量,但它很可能会低于1500 – nduplessis 2011-05-03 20:06:43

0

如何使用两个数组?其中一个是完整的数据集,另一个是已过滤的数据集。

这样你可以有两个不同的tableview,并且根据选定的段是什么,你可以在两个tableview之间做一个淡入淡出的动画。例如,假设你选择一个领域:

-(void)switchTableViews 
{ 
    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationBeginsFromCurrentState:YES]; 
    [UIView setAnimationCurve:UIViewAnimationCurveLinear]; 
    [UIView setAnimationDuration:0.5]; 
    [UIView setAnimationDidStopSelector:@selector(hideTableView)]; 

    switch (segmentedControl.selectedSegmentIndex) 
    { 
     case 0: 
     { 
     tableView1.alpha = 1.0; 
     tableView2.alpha = 0.0; 
     } 
     break; 
     case 1: 
     { 
     tableView1.alpha = 0.0; 
     tableView2.alpha = 1.0; 
     } 
     break; 
     default: 
     break; 
    } 

    [UIView commitAnimations]; 
} 

- (void)hideTableView 
{ 
    switch (segmentedControl.selectedSegmentIndex) 
    { 
     case 0: 
     { 
     tableView1.hidden = NO; 
     tableView2.hidden = YES; 
     } 
     break; 
     case 1: 
     { 
     tableView1.hidden = YES; 
     tableView2.hidden = NO; 
     } 
     break; 
     default: 
     break; 
    } 
} 

当然,这将意味着对数据源的方法,建立不同的代码集,但它并不像你想象的那么难。只需使用一个简单的if-else来检查正在设置哪个tableview。

+0

是的,它不会是很难做到的。但是您建议的解决方案不会使行向上滑动以代替被删除的行 - 它只是从一个视图到另一个视图的过渡。请前往手机 - >最新,并尝试在'全部'和'错过'之间切换,看看我想在我的应用中看到什么样的动画。 – sgosha 2011-05-03 19:48:37

+0

好吧,我想不出你想要什么替代方案来处理性能问题对不起:(你真的需要一次显示2000行吗?你能不能实现分页(一个“加载更多”的最后一个单元格在tableview中增加了100多行),这样不但可以帮助执行删除行的性能,还可以渲染tableview。除此之外,我认为我无法提供解决方案:( – Sid 2011-05-03 19:57:28

0

我绝对@nduplessis同意,你应该重新加载数据源,而不是操纵视图获取可见单元格的indexPaths。我提出了一个解决方案,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... 
}