【问题标题】:Changing the Sorting in an NSFetchedResultsController on the fly动态更改 NSFetchedResultsController 中的排序
【发布时间】:2010-12-15 12:41:35
【问题描述】:

我正在尝试通过某种分段控制动态更改 NSFetchController 中的排序。要么排序 A->Z Z->A 类型的东西。

我该怎么做才能做到这一点?我在这里关注 Jeff Lamarche 的示例:Here

我需要创建一个新的 NSFetchedResultsController 然后设置它,还是我只是创建一个新的 NSFetchRequest 并做

fetchedResultController.fetchRequest = newFetchRequest

然后我的表格会自动更新?

【问题讨论】:

    标签: iphone objective-c core-data nsfetchedresultscontroller


    【解决方案1】:

    Andreas Schaefer 的回答对我有用。诀窍是为获取请求设置一个新参数,是否是此代码:

    [[fetchedResultsController fetchRequest] setSortDescriptors:sortDescriptors];
    

    [[fetchedResultsController fetchRequest] setPredicate:predicate];
    

    在调用它之前:

    if (![[self fetchedResultsController] performFetch:&error]) {
            // Handle you error here
    }
    
    [self.tableView reloadData];
    

    看来,当您设置新参数时,NSFetchedResultsController 将根据您设置的内容执行新的 fetchrequest。如果不设置新参数,它将不会执行重新获取,而只是调用 performFetch 它不会工作..

    希望这对其他人有所帮助..

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题,我可以通过在 FetchRequestController 的 FetchRequest 上设置排序描述符来解决它,然后执行 fetch (performFetch),最后在 table view 上重新加载数据。

      NSArray *sortDescriptors = [NSArray arrayWithObject: sorter];
      [[fetchedResultsController fetchRequest] setSortDescriptors:sortDescriptors];
      NSError *error;
      if (![[self fetchedResultsController] performFetch:&error]) {
              // Handle you error here
      }
      [sorter release];
      [myTableView reloadData];
      

      这是我在不删除 FRC 或进行任何其他花哨的对象处理的情况下即时更改排序的最简单方法。我不确定这对性能的影响,如果表中的行集很大,它可能会产生影响。

      【讨论】:

      • 我使用了您的解决方案。它似乎没有滞后。但是有没有人知道这是否会从数据库中进行物理提取?
      • 请注意,更改实例化 FRC 的 fetchRequest 上的 sortDescriptors 有一个缺点。当使用委托方法controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: FRC 将对象报告为“已移动”而不是“更新”时,如文档所述,the changed attribute on the object is one of the sort descriptors used in the fetch request。 FRC 仅在其实例化时记下该键路径,因此当您稍后将 sortDescriptors 更改为其他键路径时,FRC 不会考虑它并报告“更新”而不是“移动”,反之亦然。最好制作新的FRC。
      • 在移动期间你也可以假设更新,只是用例失败
      【解决方案3】:

      不要使用 NSFetchedResultsController 作为表视图数据源,而是创建一个 NSArray,当用户使用分段控件更改排序顺序时设置该 NSArray,该数组内容基于获取的结果。然后只需使用标准数组排序进行排序。像这样的:

      - (IBAction)segmentChanged:(id)sender
      {
          // Determine which segment is selected and then set this 
          // variable accordingly
          BOOL ascending = ([sender selectedSegmentIndex] == 0);
      
          NSArray *allObjects = [fetchedResultsController fetchedObjects];
      
          NSSortDescriptor *sortNameDescriptor = 
                             [[[NSSortDescriptor alloc] initWithKey:@"name" 
                                       ascending:ascending] autorelease];
      
          NSArray *sortDescriptors = [[[NSArray alloc] 
                           initWithObjects:sortNameDescriptor, nil] autorelease];
      
          // items is a synthesized ivar that we use as the table view
          // data source.
          [self setItems:[allObjects sortedArrayUsingDescriptors:sortDescriptors]];
      
          // Tell the tableview to reload.
          [itemsTableView reloadData];    
      }
      

      所以我使用的排序描述符称为“名称”,但您可以将其更改为要在获取的结果中排序的字段的名称。此外,我引用的项目 ivar 将是您的新表视图数据源。您的表格视图代表现在将是这样的:

      - (NSInteger)tableView:(UITableView*)tableView 
       numberOfRowsInSection:(NSInteger)section
      {
          return [items count];
      }
      
      - (UITableViewCell *)tableView:(UITableView *)tableView
               cellForRowAtIndexPath:(NSIndexPath *)indexPath
      {
          // Get your table cell by reuse identifier as usual and then grab one of
          // your records based on the index path
          // ...
      
          MyManagedObject *object = [items objectAtIndex:[indexPath row]];
      
          // Set your cell label text or whatever you want 
          // with one of the managed object's fields.
          // ...
      
          return cell;
      }
      

      不确定这是否是最好的方法,但应该可以。

      【讨论】:

      • 冒着成为过早优化者的风险:在一定数量的元素之后,这会停止实用吗?如果被索引,数据库在排序方面会更有效率。
      • 这在需要对瞬态属性进行排序时也非常有用(NSFetchedResultsController 不会这样做)
      【解决方案4】:

      fetchRequest 是只读属性。您帖子中的代码行将不起作用。如果你想使用不同的获取请求,你需要用一个新的NSFetchedResultsController 替换你的控制器。您的表格不会自动重新加载。您需要在替换 NSFetchedResultsController 后的某个时间向其发送 reloadData 消息。

      【讨论】:

      • 虽然你不能创建替换 NSFetchedResultsController 的 fetchRequest 属性(它是只读的),你可以改变 fetchRequest 的属性并重新获取。这使您不必重新创建 NSFetchedResultsController。
      • 是否有可能在不创建新的 NSFetchedResultsController 的情况下更改 sectionNameKeyPath?
      • sectionNameKeyPath 是只读属性,所以我认为您需要创建一个新的NSFetchedResultsController
      猜你喜欢
      • 2013-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-27
      相关资源
      最近更新 更多