具有长长值的 CoreData 的 iOS 谓词不够精确

Posted

技术标签:

【中文标题】具有长长值的 CoreData 的 iOS 谓词不够精确【英文标题】:iOS Predicate for CoreData with long long values were not precise enough 【发布时间】:2015-02-10 08:30:10 【问题描述】:

我一直在构建的这个应用程序在 iPad 上运行,我一直在使用 XCode 6.1.1 在 ios8.1 上对其进行测试。我在尝试通过比较记录的日期(以毫秒为单位)来尝试提取记录时遇到问题。记录使用 CoreData 存储。

记录的firstDate声明如下

record.firstDate = [NSNumber numberWithLongLong:1423288915464];

在记录的.h文件中声明firstDate是这样的:

@property (nonatomic, retain) NSNumber * firstDate;

谓词是这样声明的:

NSNumber* prevStartMillis = [NSNumber numberWithLongLong:1423324800000];
NSNumber* prevEndMillis = [NSNumber numberWithLongLong:1423411199000];    

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"firstDate >= %lld AND firstDate < %lld", [prevStartMillis longLongValue], prevEndMillis longLongValue]];

我确实得到了一些 firstDate 在指定范围内的记录。但是,我得到了一些不属于指定范围的记录,例如以下 3 条记录:

...
FirstDate:1423288915464
FirstDate:1423282909663
FirstDate:1423286413320
...

以前我在另一个使用 XCode 6.1.1 的 iPhone 6 iOS8.1 应用程序上也遇到了类似的问题。我能够通过使用 %lld 为 long long 值声明谓词来解决它。但是,当我使用相同的代码时,它在 iPad 上失败了。有谁知道我做错了什么?提前致谢!

编辑 1:解决方法 我有一个解决方法(虽然不是很有效)。如果有人想知道,这是我提取记录后的代码 sn-p:

NSMutableArray* validRecords = [[NSMutableArray alloc] init];

for(Record* record in results) 
    if([record.firstDate longLongValue] >= [prevStartMillis longLongValue] && [record.firstDate longLongValue] <= [prevEndMillis longLongValue])
        [validRecords addObject:record];
   

【问题讨论】:

【参考方案1】:

您不必像您那样从NSNumber 中提取long。 您可以显式使用 NSNumber 对象来创建谓词

NSNumber* prevStartMillis = [NSNumber numberWithLongLong:1423324800000];
NSNumber* prevEndMillis = [NSNumber numberWithLongLong:1423411199000];    

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"firstDate >= %@ AND firstDate < %@", prevStartMillis, prevEndMillis];

已编辑: 我再次查看了您的代码,发现您编写的数字超出了您的范围。让我们用更短的方式写下你的长数字:

NSNumber* prevStartMillis = /*14233e+8*/;
NSNumber* prevEndMillis = /*14234e+8*/;

而且这个数字超出了范围:

...
FirstDate:14232e+8
FirstDate:14232e+8
FirstDate:14232e+8
...

所以现在很容易注意到这个数字“有点”小以满足您的条件

【讨论】:

谢谢,它也可以,但仍然不能解决我遇到的问题。 嗨,我测试了你的方式,它适用于我的情况!但是,如果指定的谓词下降到毫秒,这将不起作用,例如介于 1423324800004 到 1423324800006 之间。无论如何,我认为我不会以那种精度检查记录,所以我会将你的记录标记为正确答案!【参考方案2】:

看起来像它的有符号和无符号值问题。 您可以使用 %llu 并检查它是否有效。

【讨论】:

嗨,我试过了,还是一样。我放弃了,使用了 if 语句【参考方案3】:

解决方案是在检索记录后使用 if 语句检查日期(请参阅问题中的编辑 1)

【讨论】:

以上是关于具有长长值的 CoreData 的 iOS 谓词不够精确的主要内容,如果未能解决你的问题,请参考以下文章

具有核心数据关系的 iOS 8 Swift NSFetchResult 谓词无法访问内部 ID

用于以任何出现顺序匹配具有多个单词的列中的字符串的 Coredata 谓词

iOS Swift 复合谓词

如何在 CoreData iOS 谓词构建器中多次传递相同的参数?

CoreData:使用 IN 基于谓词/数组进行排序

核心数据:返回另一个实体的对象的谓词