【问题标题】:Filtering sectioned UITableView过滤分段的 UITableView
【发布时间】:2023-03-07 03:28:01
【问题描述】:

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

当用户在 UISegmentedControl 中选择第二个项目时,我会从表视图中删除特定行。代码如下:

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

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

【问题讨论】:

    标签: iphone objective-c cocoa-touch uitableview


    【解决方案1】:

    对于数据源的较大改动,建议您使用

    [tableView reloadData]
    

    而不是

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

    编辑:我自己没有尝试过这种方法,但考虑仅更改可见单元格集合中包含的那些行,可能在上方和下方使用缓冲区。您可以通过调用获取可见单元格的 indexPaths

    [tableView indexPathsForVisibleRows];
    

    【讨论】:

    • iOS SDK 文档是否指定了在 beginUpdatesendUpdates 之间删除/插入的建议最大行数以保持动画流畅?
    • 我不知道,但 reloadData 只关心表格视图中的可见单元格,这使它更快。我相信你可以试验确切的数量,但它很可能远低于 1500
    【解决方案2】:

    使用两个数组怎么样?其中一个是完整的数据集,另一个是过滤后的数据集。

    这样你可以有两个不同的tableviews,并且根据选择的segment,你可以在两个tableviews之间做一个淡入淡出动画。例如,假设您选择了一个细分:

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

    【讨论】:

    • 是的,这并不难。但是您建议的解决方案不会使行向上滑动以代替被删除的行-这只是从一个视图到另一个视图的过渡。请转到电话->最近并尝试在“全部”和“错过”之间切换,看看我想在我的应用中看到什么样的动画。
    • 嗯,我想不出一个替代你想要的东西来处理性能问题对不起:(你真的需要一次显示 2000 行吗?你不能实现分页(“加载更多”在最后一个单元格上添加了 100 多行到 tableview)。这将真正有助于提高性能,不仅是删除行,而且还呈现 tableview。除此之外,我认为我无法提供解决方案 :(
    【解决方案3】:

    我绝对同意@nduplessis 的观点,即您应该重新加载数据源而不是操纵视图。我为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-02-05
      • 1970-01-01
      • 1970-01-01
      • 2015-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-16
      • 2018-04-09
      相关资源
      最近更新 更多