Core Data NSPredicate “deleted == NO” does not work as expected

耗尽温柔 提交于 2019-12-17 03:20:22

问题


I am using UIManagedDocument with Parent Child context.

In my child context I do the following

Code 1

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

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

}]];

Above code returns the expected results (only Not deleted members for the event).

Code 2

But this code does not. It fetches all records.

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

It seems confusing. Both should return same results, but predicateWithBlock returns correct results where as predicateWithFormat returns all records.

What are the pros and cons of using predicateWithBlock instead of predicateWithFormat?


回答1:


The problem is that you have defined an attribute deleted for your entity. That conflicts with the isDeleted method of NSManagedObject, so you should rename that attribute.

The following "experiment" shows that strange things happen if you call your attribute "deleted" (c is a managed object with a custom deleted attribute):

// 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

Your "Code 1" refers to the property, therefore it returns the expected result. "Code 2" uses Key-Value Coding, and [c valueForKey:@"deleted"] returns YES if the object actually has been deleted from the context!

So renaming that attribute should solve your problem. Unfortunately the compiler does not emit warnings if an attribute name conflicts with a built-in method.




回答2:


Use the formatting placeholder to replace the bool value:

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

Your use of the key path is probably ok, but the right-hand side probably doesn't look like "NO" to the parser.



来源:https://stackoverflow.com/questions/16000242/core-data-nspredicate-deleted-no-does-not-work-as-expected

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!