在运行中更改NSFetchedResultsController中的排序

ale*_*erc 17 iphone core-data objective-c nsfetchedresultscontroller

我试图通过某种分段控制动态地改变NSFetchController中的排序.要么排序A-> Z Z-> A型的东西.

我该怎么做才能做到这一点?我跟随Jeff Lamarche的例子:这里

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

fetchedResultController.fetchRequest = newFetchRequest
Run Code Online (Sandbox Code Playgroud)

然后我的表会自动更新?

小智 32

我遇到了同样的问题,我可以通过在FetchRequestController的FetchRequest上设置排序描述符来修复它,然后执行fetch(performFetch),最后在表视图上重新加载数据.

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

这是我在不丢弃FRC或进行任何其他花哨的对象处理的情况下处理动态排序的最简单方法.我不确定性能对此的影响,如果表中的行集很大,它可能会产生影响.

  • 请注意,在实例化的 FRC 的 fetchRequest 上更改 sortDescriptor 有一个缺点。当使用委托方法 `controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:` 时,FRC 将对象报告为“已移动”而不是“已更新”,正如文档所述,“对象上的已更改属性是获取请求`。FRC 仅在其实例化时记录该键路径,因此当您稍后将 sortDescriptor 更改为其他键路径时,FRC 不会考虑它并报告“更新”而不是“移动”,反之亦然。最好制作新的 FRC。 (2认同)

Mat*_*ong 8

不要使用NSFetchedResultsController作为表视图数据源,而是创建一个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];    
}
Run Code Online (Sandbox Code Playgroud)

因此我使用的排序描述符称为"名称",但您可以将其更改为要在提取的结果中排序的字段的名称.此外,我引用的项目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;
}
Run Code Online (Sandbox Code Playgroud)

不确定这是否是最佳方式,但它应该有效.