我有一个NSManagedObject
子类Foo
,它有两个建模属性:a
和b
。
a
和b
是NSString
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
肯定不 {{ 1}}。
事实上,我甚至可以通过调整我的谓词来证明:
nil
哪个工作正常,并将10个对象返回给我。
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"a != nil"];
/ NSPredicate
的这种行为很简单,我无法弄清楚为什么它会为NSFetchRequest
谓词返回一个空结果,其中a != b
是b
null
。但是当我将其更改为a != nil
(这只是b
的硬编码值时)工作正常!!)
编写了一些测试代码来探讨这个问题,似乎在比较密钥时,如果==
属性的LHS或RHS是nil
,那么结果数组是空的。 / p>
另一方面,如果LHS和RHS都是非nil
,那么它似乎工作正常。
我在这里缺少什么?为什么==
运算符在比较其中一个或两个都是nil
的两个键时会失败?
答案 0 :(得分:2)
nil
值在SQLite数据库中存储为NULL
,SQLite将NULL
视为
“未定义的价值”。谓词“a!= b”被转换为SQLite查询
SELECT ... FROM ZENTITY t0 WHERE t0.ZA <> t0.ZB
并且不返回t0.ZA
或t0.ZB
为NULL(又名“未定义”)的任何行。
因此,a != b
不会返回a
或b
为nil
的任何对象。
出于同样的原因,谓词a == b
不返回a
的对象
b
为nil
。
另一方面,谓词a != nil
与
SELECT ... FROM ZENTITY t0 WHERE t0.ZA IS NOT NULL
使用“IS NOT”代替“&lt;&gt;”。因此,此查询确实返回所有对象
a != nil
(正如人们所料)。
我不知道Core Data文档中是否明确记录了此行为 (我还没有搜索过),但这就是SQLite如何处理NULL值,它应该解释 你观察到的行为。
如果添加启动参数
,则可以看到SQLite语句-com.apple.CoreData.SQLDebug 3
表示Scheme编辑器中的可执行文件。
更新:来自“核心数据编程指南”中的"Attributes":
您可以指定属性是可选的 - 也就是说,不是 需要有价值。但是,一般来说,你是沮丧的 从这样做 - 特别是对于数值(通常你可以得到 使用带有默认值的强制属性的更好结果 模型 - 0)。原因是SQL有特殊的比较 与Objective-C的nil不同的NULL行为。数据库中为NULL 与0不同,搜索0与列不匹配 NULL。
这至少提到可选属性是特殊的,可能不是 表现得像预期的那样。
"Predicate Programming Guide"还有一个关于NULL值和测试NULL的部分。