iphone - NSPredicate 比较可能为 nil 的键

标签 iphone ios core-data nspredicate nsmanagedobject

我有一个NSManagedObject子类Foo它有两个建模属性:ab .

abNSString s,但不能保证它们会被实例化——它们也可能是 nil 。事实上,正如现在所发生的那样,所有Foo实例有b等于 nil .

我想获取所有Foo对象使得 a != b :

NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Foo"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"a != b"];    
NSArray *result = [managedObjectContext executeFetchRequest:fetchRequest error:nil];

结果数组是空的,即使我知道事实我有 10 个对象,其中 a绝对不是 nil .

事实上,我什至可以通过将谓词调整为来证明这一点:

fetchRequest.predicate = [NSPredicate predicateWithFormat:@"a != nil"];

效果很好,并返回给我 10 个对象。

NSPredicate的这种行为/NSFetchRequest很奇怪,我不明白为什么它返回原始 a != b 的空结果谓词 where bnull 。但是当我将其更改为 a != nil 时效果很好(无论如何,这只是 b 的硬编码值!!)

编写了一些更多的测试代码来探讨这个问题,似乎在比较键时,如果 == 的 LHS 或 RHS属性是 nil ,则结果数组为空。

另一方面,如果 LHS 和 RHS 均非 nil ,那么它似乎工作正常。

我在这里缺少什么?为什么 ==比较两个键(其中一个或两个为 nil)时,运算符失败?

最佳答案

nil 值在 SQLite 数据库中存储为 NULL,并且 SQLite 将 NULL 视为 “未定义的值”。谓词“a != b”被转换为 SQLite 查询

SELECT ... FROM ZENTITY t0 WHERE  t0.ZA <> t0.ZB

并且不会返回任何 t0.ZAt0.ZB 为 NULL(也称为“未定义”)的行。 因此,a != b 不会返回任何 abnil 的对象。

出于同样的原因,谓词 a == b 不会返回同时包含 a 的对象 和 bnil

另一方面,谓词 a != nil 的翻译略有不同

SELECT ... FROM ZENTITY t0 WHERE   t0.ZA IS NOT NULL

使用“IS NOT”代替“<>”。因此这个查询实际上返回所有对象 a != nil(正如人们所期望的那样)。

我不知道核心数据文档中是否明确记录了此行为 (我还没有搜索过),但这就是 SQLite 处理 NULL 值的方式,它应该解释 您观察到的行为。

如果添加启动参数,您可以看到 SQLite 语句

-com.apple.CoreData.SQLDebug 3

用于方案编辑器中的可执行文件。

更新:来自"Attributes"在《核心数据编程指南》中:

You can specify that an attribute is optional—that is, it is not required to have a value. In general, however, you are discouraged from doing so—especially for numeric values (typically you can get better results using a mandatory attribute with a default value—in the model—of 0). The reason for this is that SQL has special comparison behavior for NULL that is unlike Objective-C's nil. NULL in a database is not the same as 0, and searches for 0 will not match columns with NULL.

这至少提到可选属性是特殊的并且可能不是 按预期行事。

"Predicate Programming Guide"还有一个关于 NULL 值和 NULL 测试的部分。

关于iphone - NSPredicate 比较可能为 nil 的键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17699511/

相关文章:

iphone - 由于未捕获的异常 'NSInvalidArgumentException' 而终止应用程序,原因 : 'executeFetchRequest:error: A fetch request must have an entity.'

ios - NSFetchedResultsController "cannot access fetched objects before -performFetch:"调用 objectAtIndexPath : 时崩溃

iphone - 将 CLLocation 移动 x 米

iphone - NSUserDefaults boolForKey 出现意外结果

objective-c - 使用 XMLParser 访问正确的 XML 节点

iphone - 将 dispatch_async 与核心数据一起使用时获取 EXC_BAD_ACCESS

html - Iphone Ipad 的媒体查询

c++ - Xcode iPhone : Removing text from a . txt 文件

javascript - 如何在此示例 Codepen 上使用 Ipad Safari? (看起来像一场噩梦)

ios - writeCopy 后出现 RLMException "Realm at path ' ' already opened with different encryption key"(toFile :, 加密 key :)