2

我正在使用带有父子上下文的 UIManagedDocument。

在我的孩子上下文中,我执行以下操作

代码 1

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

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

}]];

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

代码 2

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

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"deleted == NO"];
NSSet *results = [self.event.memberships filteredSetUsingPredicate:predicate];

这似乎令人困惑。两者都应该返回相同的结果,但在 as返回所有记录predicateWithBlock的情况下返回正确的结果。predicateWithFormat

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

4

2 回答 2

8

问题是您已经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

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

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

于 2013-04-14T20:19:14.900 回答
0

使用格式化占位符替换布尔值:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", @"deleted", @(NO)];

您对密钥路径的使用可能没问题,但右侧可能看起来不像解析器的“否”。

于 2013-04-14T17:20:35.763 回答