I am trying to generate predicate editor templates for my Core Data entities. In my code I have the following:
NSEntityDescription *descrip = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:managedObjectContext];
NSArray *templates = [NSPredicateEditorRowTemplate templatesWithAttributeKeyPaths:[NSArray arrayWithObjects:@"name", @"age", nil] inEntityDescription:descrip];
[ibPredicateEditor setRowTemplates: templates];
NSPredicate *p = [NSPredicate predicateWithFormat:@"name like 'John'"];
[ibPredicateEditor setObjectValue:p];
Printing out the contents of the templates array gives me the following:
CFArray 0x1002d7400 [0x7fff70ff5f20] {type = immutable, count = 2, values = ( 0 : NSPredicateEditorRowTemplate 0x10025c090: [name] [99, 4, 5, 8, 9] NSStringAttributeType 1 : NSPredicateEditorRowTemplate 0x1002d2dc0: [age] [4, 5, 0, 2, 1, 3] NSInteger16AttributeType )}
When this code executes I get the following on the console:
Warning - unable to find template matching predicate name LIKE "John"
The interface for doing this looks extremely straight forward, so I can't seem to figure out what I am doing wrong. Any help would be greatly appreciated!
EDIT
My original issue was that I was using the LIKE operator when my templates did not support it. However I am confused about why I get a similar warning when passing in a compound predicate into the editor.
NSPredicate *p = [NSPredicate predicateWithFormat:@"name CONTAINS 'John'"];
NSPredicate *p2 = [NSPredicate predicateWithFormat:@"name CONTAINS 'Jo'"];
NSPredicate *final = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:p, p2, nil]];
[ibPredicateEditor setObjectValue: final];
OR
NSPredicate *final = [NSCompoundPredicate orPredicateWithSubpredicates:[NSArray arrayWithObjects:p, p2, nil]];
[ibPredicateEditor setObjectValue: final];
Both of these produce similar warnings as my initial issue. However, I find it odd that I can use a single predicate and build a compound and predicate, but I can't pass a prebuilt compound and predicate into the editor.
The default templates supplied by NSPredicateEditorRowTemplate
for NSString
key-paths do not support comparisons with the LIKE operator.
In the templates you generated there is a list of the operators it does support:
NSPredicateEditorRowTemplate 0x10025c090: [name] [99, 4, 5, 8, 9] NSStringAttributeType
[99, 4, 5, 8, 9]
indicates that the name NSString
attribute supports:
4 – Equal To
5 – Not Equal To
8 – Begins With
9 – Ends With
99 – Contains
(found in NSComparisonPredicate.h)
CONTAINS is similar to LIKE without % and _ substitutions. If you require that you can always initialize your own template array.
The syntax is a bit verbose.
NSExpression *nameExpression = [NSExpression expressionForKeyPath:@"name"];
NSArray *operators = [NSArray arrayWithObjects:
[NSNumber numberWithInt: NSEqualToPredicateOperatorType],
[NSNumber numberWithInt:NSNotEqualToPredicateOperatorType],
[NSNumber numberWithInt:NSLikePredicateOperatorType],
[NSNumber numberWithInt:NSBeginsWithPredicateOperatorType],
[NSNumber numberWithInt:NSEndsWithPredicateOperatorType],
[NSNumber numberWithInt:NSContainsPredicateOperatorType],
nil];
NSUInteger options = (NSCaseInsensitivePredicateOption |
NSDiacriticInsensitivePredicateOption);
NSPredicateEditorRowTemplate *template = [[NSPredicateEditorRowTemplate alloc]
initWithLeftExpressions:[NSArray arrayWithObject:nameExpression]
rightExpressionAttributeType:NSStringAttributeType
modifier:NSDirectPredicateModifier
operators:operators
options:options];