如何使用 NSFetchedResultsController 按字母顺序对 UITableView 进行排序?

Posted

技术标签:

【中文标题】如何使用 NSFetchedResultsController 按字母顺序对 UITableView 进行排序?【英文标题】:How can I sort my UITableView alphabetically with NSFetchedResultsController? 【发布时间】:2011-04-14 08:22:19 【问题描述】:

当用户按下“按字母顺序排序”时,我为我的表格调用以下方法:

- (void) sortByName

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

    NSMutableArray *items = [[fetchedResultsController fetchedObjects] mutableCopy];
    [items sortUsingDescriptors:sortDescriptors];

    int newDisplayOrder = 0;

    for (NSManagedObject *managedObject in items)
    
        [managedObject setValue:[NSNumber numberWithInt:newDisplayOrder++ ] forKey:@"displayOrder"];
    

    [sortDescriptor release];
    [sortDescriptors release];

    // Save the context.
    NSError *error = nil;
    if (![self.managedObjectContext save:&error])
    
       // Need code to handle error properly
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
            

但由于某种原因,它似乎不是按字母顺序排序,而是将每个项目按其创建顺序排列。我做错了什么?

【问题讨论】:

【参考方案1】:

看起来不错。

您是否设置了获取结果控制器以根据displayOrder 进行排序?

此外,您应该释放代码中的项目...

【讨论】:

我分配的唯一两个项目是 NSSortDescriptor 和 NSArray,我都发布了这两个项目 - 我还漏掉了什么吗? 我已经仔细检查了获取的结果控制器是否根据 displayOrder 进行排序。 (不过是个好建议-当我阅读您的答案时,我确信会是这样)。奇怪的是,它确实重新排列了表格,但它把所有东西都按照它们最初添加的顺序。 这很奇怪......我删除了应用程序的数据并放入了一些新的测试数据,它开始工作了。似乎代码一直都是正确的。也许是我更改影响 displayOrder 属性的方法之前的旧应用数据? mutableCopy 创建一个容器的副本,这个副本的retainCount 为1。您应该在使用后释放它。或者,至少,自动释放...【参考方案2】:

您似乎没有使用排序后的数组刷新 tableview。我在我的一个项目中使用以下方法根据状态和姓名对一组联系人进行排序:

- (void)refresh 
    if ([NSThread isMainThread]) 
        NSSortDescriptor *descriptorStatus = [[[NSSortDescriptor alloc] initWithKey:@"status" ascending:NO selector:@selector(statusCompare:)] autorelease];
        NSSortDescriptor *descriptorName = [[[NSSortDescriptor alloc] initWithKey:@"displayName" ascending:YES] autorelease]; 
        [contactArray sortUsingDescriptors:[NSArray arrayWithObjects:descriptorStatus, descriptorName, nil]];

        [tableView reloadData];
     else 
        [self performSelectorOnMainThread:@selector(refresh) withObject:nil waitUntilDone:NO];
    

对于您的项目,您可能不必检查是否在主线程上执行刷新,除非从除主线程之外的任何线程检索数据。

【讨论】:

【参考方案3】:

试试这个:

NSMutableArray *items = [NSMutableArray arrayWithArray:fetchedResultsController.fetchedObjects];

或一步完成(不需要是可变的):

NSArray *items = [fetchedResultsController.fetchedObjects sortedArrayUsingDescriptors:sortDescriptors];

顺便说一句,这似乎是一种对表格进行排序的复杂方式。您正在修改数据库中的 displayIndex 以反映新的排序顺序。推测 NSFetchRequest 驱动 fetchedResultsController 是基于 displayIndex 排序的。

这会更简单,不需要更改数据库,只需更改 fetchRequest 并重新配置 fetchedResultsController。

来自 NSFetchedResultsController 文档:

修改获取请求

你不能 只需将获取请求更改为 修改结果。如果你想 更改获取请求,您必须:

如果您正在使用缓存,请将其删除 (使用 deleteCacheWithName:)。 通常你不应该使用缓存 如果您正在更改获取请求。

更改获取请求。调用 执行抓取:。

【讨论】:

【参考方案4】:

为什么不在获取对象时设置排序描述符。

【讨论】:

这不是说在创建 *items 之前调用它的方法吗?

以上是关于如何使用 NSFetchedResultsController 按字母顺序对 UITableView 进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

启动 Core Data 应用程序时在后台配置 NSFetchedResultsController

为啥不能两次获取相同的数据? NSFetchedResultsController 为空

[精选] Mysql分表与分库如何拆分,如何设计,如何使用

如果加入条件,我该如何解决。如果使用字符串连接,我如何使用

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]