在运行中更改NSFetchedResultsController中的排序

时间:2009-11-11 16:03:02

标签: iphone objective-c core-data nsfetchedresultscontroller

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

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

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

fetchedResultController.fetchRequest = newFetchRequest

然后我的表会自动更新?

4 个答案:

答案 0 :(得分: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];

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

答案 1 :(得分:8)

不使用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];    
}

因此我使用的排序描述符称为“name”,但您可以将其更改为要在获取的结果中排序的字段的名称。此外,我引用的项目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;
}

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

答案 2 :(得分:3)

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

[[fetchedResultsController fetchRequest] setSortDescriptors:sortDescriptors];

OR

[[fetchedResultsController fetchRequest] setPredicate:predicate];

在致电之前:

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

[self.tableView reloadData];

看来,当你设置一个新参数时,NSFetchedResultsController会根据你设置的内容执行一个新的fetchrequest。如果不设置新参数,它将不会执行重新获取并只调用{{1}它不起作用..

希望这有助于其他人..

答案 3 :(得分:2)

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