核心数据NSPredicate"已删除==否"无法按预期工作

kri*_*nan 1 core-data objective-c nspredicate uimanageddocument

我正在使用UIManagedDocument与父子上下文.

在我的孩子背景下,我做了以下几点

代码1

NSSet *results = [self.event.memberships filteredSetUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {

    return ([[evaluatedObject deleted] boolValue] == NO);

}]];
Run Code Online (Sandbox Code Playgroud)

上面的代码返回预期的结果(仅事件的未删除成员).

代码2

但是这段代码没有.它获取所有记录.

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"deleted == NO"];
NSSet *results = [self.event.memberships filteredSetUsingPredicate:predicate];
Run Code Online (Sandbox Code Playgroud)

这似乎令人困惑.两者都应该返回相同的结果,但predicateWithBlock返回正确的结果,其中predicateWithFormat返回所有记录.

使用predicateWithBlock代替的优缺点是predicateWithFormat什么?

Mar*_*n R 7

问题是您已deleted为实体定义了属性.这与isDeleted方法冲突NSManagedObject,因此您应该重命名该属性.

以下"实验"表明,如果将属性称为"已删除"(c具有自定义deleted属性的托管对象),则会发生奇怪的事情:

// Set custom "deleted" property to YES:
c.deleted = @YES;

// Use the property, as your Code 1
NSLog(@"%@", [c deleted]);
// Output: 1

// Use Key-Value Coding, as your Code 2
NSLog(@"%@", [c valueForKey:@"deleted"]);
// Output: 0

// Now really delete the object and try again:
[context deleteObject:c];
NSLog(@"%@", [c valueForKey:@"deleted"]);
// Output: 1
Run Code Online (Sandbox Code Playgroud)

您的"代码1"指的是该属性,因此它返回预期的结果."代码2"使用键值编码,如果对象实际上已从上下文中删除,则[c valueForKey:@"deleted"]返回YES!

因此重命名该属性应该可以解决您的问题.遗憾的是,如果属性名称与内置方法冲突,编译器不会发出警告.