NSPredicate not working with calculated field

2019-05-27 03:28发布

问题:

I have a Core Data project and am having difficulty searching the data with a simple calculated field and have no idea why it's not working.

I have a Tutor entity, with core data string attributes "tutorFirstName" and "tutorLastName". I've created an additional string attribute "tutorFullName" which is populated in a Category as such:

NSString *fullName = [@[self.tutorFirstName, self.tutorLastName] componentsJoinedByString:@" "];

The data is populated fine, but when I perform the following searches only the predicates on the tutorFirstName and tutorLastName work:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"tutorFirstName = %@", @"Sean"];
[fetchRequest setPredicate:predicate];
NSArray *fetchedObjects = [moc executeFetchRequest:fetchRequest error:&error];
NSLog(@"Search on %@ returned %lu items (%@)",predicate, (unsigned long)fetchedObjects.count, [fetchedObjects objectAtIndex:0]);

predicate = [NSPredicate predicateWithFormat:@"tutorFullName = %@", @"Sean Silverman"];
[fetchRequest setPredicate:predicate];
fetchedObjects = [moc executeFetchRequest:fetchRequest error:&error];
NSLog(@"Search on %@ returned %lu items",predicate, (unsigned long)fetchedObjects.count);

predicate = [NSPredicate predicateWithFormat:@"tutorLastName = %@", @"Silverman"];
[fetchRequest setPredicate:predicate];
fetchedObjects = [moc executeFetchRequest:fetchRequest error:&error];
NSLog(@"Search on %@ returned %lu items (%@)",predicate, (unsigned long)fetchedObjects.count, [fetchedObjects objectAtIndex:0]);

Here is the debug code showing the results of each search and also that the resulting core data object DOES have the correct tutorFullName entry.

2014-01-21 14:05:26.129 AT Data[54935:70b] Search on tutorFirstName == "Sean" returned 1 items (<Tutor: 0x113b16830> (entity: Tutor; id: 0xd0000000041c0006 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Tutor/p263> ; data: {
charges =     (
    "0xd000000581b40002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p90221>",
    "0xd00000058b280002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p90826>",
    "0xd00000057d4c0002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p89939>",
    "0xd0000005994c0002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p91731>",
    "0xd000000593c40002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p91377>",
    "0xd0000005aa3c0002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p92815>",
    "0xd0000005ab440002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p92881>",
    "0xd0000005aa500002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p92820>",
    "0xd00000057ea00002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p90024>",
    "0xd0000005a7000002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p92608>",
    "(...and 595 more...)"
);
tutorFirstName = Sean;
tutorFullName = "Sean Silverman";
tutorLastName = Silverman;

2014-01-21 14:05:26.130 AT Data[54935:70b] Search on tutorFullName == "Sean Silverman" returned 0 items

2014-01-21 14:05:26.131 AT Data[54935:70b] Search on tutorLastName == "Silverman" returned 1 items (<Tutor: 0x113b16830> (entity: Tutor; id: 0xd0000000041c0006 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Tutor/p263> ; data: {
charges =     (
    "0xd000000581b40002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p90221>",
    "0xd00000058b280002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p90826>",
    "0xd00000057d4c0002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p89939>",
    "0xd0000005994c0002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p91731>",
    "0xd000000593c40002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p91377>",
    "0xd0000005aa3c0002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p92815>",
    "0xd0000005ab440002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p92881>",
    "0xd0000005aa500002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p92820>",
    "0xd00000057ea00002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p90024>",
    "0xd0000005a7000002 <x-coredata://B8C4C087-A68F-4CA6-935D-F596CB1E9D0C/Charge/p92608>",
    "(...and 595 more...)"
);
tutorFirstName = Sean;
tutorFullName = "Sean Silverman";
tutorLastName = Silverman;

The only thing that seems strange to me is that, in the debug output of the entity, the strict core data attributes do not have the double-quotes around the string value, but the calculated attribute does ("Sean Silverman"), but that may only be because there's a space in the calculated attribute.

Any help would be greatly appreciated.

回答1:

By calculated, I assume you mean that the property is transient. If this is the case then you are not able to search on those properties. This is because the property may not be created at the time that the search is executed for all the core data entities you are searching on. From the Core Data Programming Guide (just after Listing 1):

You cannot fetch using a predicate based on transient properties (although you can use transient properties to filter in memory yourself).

So, if you would like to use a predicate to filter on that property you will need to make the attribute non transient.