【问题标题】:NSSortDescriptor sort a string field as a number with comparator block not workingNSSortDescriptor 将字符串字段排序为数字,比较器块不起作用
【发布时间】:2012-04-30 21:34:27
【问题描述】:

我有一个充满第三方 ID 的字段。 id 是数字,但作为字符串写入数据库。

我想根据这个 id 对整数的值进行排序。所以我将这个NSSortDescriptor 添加到NSFetchRequest

NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
[numFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSSortDescriptor *sortBy = [[NSSortDescriptor alloc] initWithKey:@"someId" ascending:YES comparator:^(id a, id b) {
    return [[numFormatter numberFromString:a] compare:[numFormatter numberFromString:b]];
}];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortBy]];

但我得到如下结果。这些仍然按字母顺序排列为字符串。

730275292
73900038
730172867
7350727
830138437
835164
837287901
8338804
930274
9324376

我对使用这个比较器块有什么不明白的地方?

编辑 2012 年 5 月 1 日美国东部标准时间上午 9:20

为了测试是否使用了比较器块,我尝试了以下根据字段的长度进行排序。

NSSortDescriptor *sortBy = [[NSSortDescriptor alloc] initWithKey:@"fbId" ascending:YES comparator:^(id a, id b) {
    if ([a length] < [b length]) {
        return NSOrderedAscending;
    } else if ([a length] > [b length]) {
        return NSOrderedDescending;
    } else {
        return NSOrderedSame;
    }
}];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortBy]];

我仍然得到按字母顺序排序的结果!所以这让我觉得比较器块甚至没有被使用。

716164250
726354466
73900038
739600038
7450727
810138437
801164
801375346
8213997

【问题讨论】:

  • numFormatter 返回什么?诠释?字符串?
  • NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init]; [numFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
  • 您是否尝试在比较器块本身中设置断点以查看它是否被调用?如果它被调用,那么你可以确定它是错误的块代码。
  • 啊,我之前从那里尝试过 NSLogging,只是尝试放入断点。不去,它不会被调用。

标签: ios core-data


【解决方案1】:

试试这个!

[NSSortDescriptor sortDescriptorWithKey:@"name"
ascending:YES
selector:@selector(localizedStandardCompare:)]

【讨论】:

  • 如果名称数据类型为双精度,则不会对名称进行排序
【解决方案2】:

我不使用 NSFetchRequest,所以我无法对此进行具体评论,但它似乎与它相关。您在比较器块中使用的代码很好。我设置了一个包含您显示的确切数字的数组,然后使用您的代码对它们进行排序,一切正常:

    NSArray *array = [NSArray arrayWithObjects:@"730275292",
                      @"73900038",
                      @"730172867",
                      @"7350727",
                      @"830138437",
                      @"835164",
                      @"837287901",
                      @"8338804",
                      @"930274",
                      @"9324376", nil];
    NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
    [numFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
    NSArray *sArray = [array sortedArrayUsingComparator:^(id a, id b) {
        return [[numFormatter numberFromString:a] compare:[numFormatter numberFromString:b]];
    }];
    NSLog(@"%@",sArray);

当上面的代码运行时,我得到一个日志:

(
    835164,
    930274,
    7350727,
    8338804,
    9324376,
    73900038,
    730172867,
    730275292,
    830138437,
    837287901
)

我相信这是您正在寻找的顺序。您可能会考虑在收到获取请求的结果后将它们排序到一个数组中。我怀疑数组是否进行排序或获取请求是否进行排序是否重要。很可能使用其中一种并没有性能提升。

如果您仍然希望 NSFetchRequest 进行排序,那么您可能会缺少一些东西以使其正确排序。老实说,我不确定,因为我没用过。

更新

快速浏览 NSFetchRequest 文档,我发现有一些参数会影响排序。例如,在resultType 的文档中,它给出了这样的信息:

您使用 setResultType: 设置返回对象的实例类型 从执行请求——有关可能的值,请参阅 “NSFetchRequestResultType。”如果将值设置为 NSManagedObjectIDResultType,这会将任何排序顺序降级为 如果您未将属性值包含在 请求。

所以看起来返回类型可能会影响您的排序。

【讨论】:

  • stackoverflow.com/questions/4789782/… 的最佳答案表明某些objective-c 比较器块不能“编译”成SQL,并且基本上建议了您的建议。嗯,合理的解决方法,但我很想知道为什么比较器块不起作用的真正答案。此外,这通常不是解决方案,因为将数据放在 NSFetchResultsController 中可能很重要(例如,当您在 TableView 中使用它并利用 NSFetchedResultsControllerDelegate 更新 UI 时)。
  • 好吧,我只是更新答案。我在 NSFetchRequest 中搜索了“排序”,发现resultType 会影响排序。你可能想调查一下。不幸的是,我直接使用 SQLite,而不是使用 Core Data,所以这与我的知识范围有关。
  • 真正的答案正是您所指出的——获取请求无法将比较器块转换为 SQL,因此依赖于这些块的排序描述符不适用于 Core Data 获取请求。该答案中的文档链接更详细地解释了它。
猜你喜欢
  • 2019-03-12
  • 1970-01-01
  • 2022-12-05
  • 2011-09-20
  • 2014-04-03
  • 2012-01-22
  • 2017-12-07
  • 1970-01-01
相关资源
最近更新 更多