简体   繁体   English

过滤分段 UITableView

[英]Filtering sectioned UITableView

My application have UI similar to Phone.app->Recents: sectioned UITableView and a UISegmentedControl in the navigation bar.我的应用程序的 UI 类似于 Phone.app->Recents: sectioned UITableView 和导航栏中的 UISegmentedControl。 What I want to do is display full set of data if first section is selected and display filtered set of data if second section is selected.如果选择了第一部分,我想要做的是显示完整的数据集,如果选择了第二部分,则显示过滤的数据集。

When user selects second item in UISegmentedControl I delete specific rows from the table view.当用户在 UISegmentedControl 中选择第二个项目时,我会从表视图中删除特定行。 Here is the code:这是代码:

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

The code above works fine except for one serious issue: performance.上面的代码运行良好,除了一个严重的问题:性能。 Deleting 1500 out of 2200 rows takes about 20 seconds.从 2200 行中删除 1500 行大约需要 20 秒。 That is obviously unacceptable.这显然是不可接受的。 What is the best approach to filtering table view rows with animation?使用 animation 过滤表视图行的最佳方法是什么?

For large changes to your data source, it is recommended that you use对于数据源的较大更改,建议您使用

[tableView reloadData]

instead of代替

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

EDIT: I haven't tried this approach myself, but consider altering only those rows that are contained in the collection of visible cells, perhaps with a buffer above and below.编辑:我自己没有尝试过这种方法,但考虑只更改可见单元格集合中包含的那些行,可能在上方和下方使用缓冲区。 You can get the indexPaths of the visible cells by calling您可以通过调用获取可见单元格的 indexPaths

[tableView indexPathsForVisibleRows];

I definitely agree with @nduplessis that you should reload the dataSource rather than manipulating the view.我绝对同意@nduplessis,您应该重新加载数据源而不是操纵视图。 I proposed a solution to a similar question here that would indeed cause your rows to slide up.在这里提出了一个类似问题的解决方案,这确实会导致你的行向上滑动。

The basic idea is to call reloadSections:withRowAnimation: and in your UITableViewDataSource methods switch on the segmented control's selectedSegmentIndex.基本思想是调用 reloadSections:withRowAnimation: 并在您的 UITableViewDataSource 方法中打开分段控件的 selectedSegmentIndex。

Assuming your data is flat (only one section) it would look something like this:假设您的数据是平坦的(只有一个部分),它看起来像这样:

- (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...
}

How about using a two arrays?使用两个 arrays 怎么样? One of them is the full data set and the other one is the filtered dataset.其中一个是完整的数据集,另一个是过滤后的数据集。

This way you can have two different tableviews, and depending on what the selected segment is, you could do a fade animation between the two tableviews.这样,您可以拥有两个不同的表格视图,并且根据所选段是什么,您可以在两个表格视图之间进行渐变 animation。 For example, lets say you select a segment:例如,假设您 select 一个段:

-(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;
   }
}

Of course, this would mean setting up different code sets for the datasource methods but it's not as difficult as you think.当然,这意味着为数据源方法设置不同的代码集,但这并不像您想象的那么难。 Just use a simple if-else to check for which tableview is being set.只需使用一个简单的 if-else 来检查正在设置的 tableview。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM