NSPredicateEditorRowTemplate and CoreData - cocoa

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];

It may be a problem with the LIKE operator. This code logs no warning:
NSPredicate *p;
p = [NSPredicate predicateWithFormat:#"name == 'John'"];
[ibPredicateEditor setObjectValue:p];
p = [NSPredicate predicateWithFormat:#"age > 18"];
[ibPredicateEditor setObjectValue:p];

Related

Removing unwanted characters from json response

I am trying to load data from a json response stored in an NSArray into a tableview.
json:
"fulltime": [
2,
2
],
Above is the json but when I display to screen it looks like the below code.
( 2, 2)
I have tried using the following to remove unwanted characters the brackets () in this case but i am getting the warning below the code.
NSArray *place= [jsonResults objectAtIndex:indexPath.row];
NSString *score= [place valueForKey:#"fulltime"];
Firstly tried this:
NSString *score = [[[place valueForKey:#"fulltime"]objectAtIndex:indexPath.row] stringByReplacingOccurrencesOfString:#"(" withString:#""];
And then this:
NSString *jsonstring = [score stringByReplacingOccurrencesOfString:#"\)\n" withString:#""];
jsonstring = [jsonstring stringByReplacingOccurrencesOfString:#"\t" withString:#""];
This is the error i get each time:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber stringByReplacingOccurrencesOfString:withString:]: unrecognized selector sent to instance 0x1f55f270'
I am not sure is it a problem with the way i am trying o remove the characters or the way i am parsing the data. Below is a better view of the json, everything else parses fine up until i want to access "fulltime"
"date": "2013-03-17 16:00:00",
"home_id": 8455,
"home": "Chelsea",
"homeshort": "Chelsea",
"away_id": 8654,
"away": "West Ham United",
"awayshort": "West Ham",
"status": "Finished",
"halftime": [1, 0],
"fulltime": [2, 0],
"extratime": [0, 0],
"penalties": [0, 0],
try like this may be it'l helps you,
[[[jsonarray objectAtIndex:0] valueForKey:#"fulltime"] objectAtIndex:0]
Not sure if I understood what you want, but to parse those numbers I would do something like:
NSDictionary * place= [jsonResults objectAtIndex:indexPath.row];
NSArray * fulltime = [place valueForKey:#"fulltime"];
NSNumber * num1 = [fulltime objectAtIndex:0];
NSNumber * num2 = [fulltime objectAtIndex:1];
NSLog(#"Fulltime is %d, %d", [num1 intValue], [num2 intValue]);

XCODE Let me know how to sort numeric size

The following is my code:
NSArray *myarr = [[NSArray alloc]initWithObjects:#"2",#"13",#"1",#"21",#"300",#"4", nil];
NSSortDescriptor *desc = [[NSSortDescriptor alloc]initWithKey:#"self" ascending:YES];
NSArray *rrrr = [myarr sortedArrayUsingDescriptors:[NSArray arrayWithObject:desc]];
NSLog(#"%#",rrrr);
The following is my result:
1,
13,
2,
21,
300,
4
While the following is my expected result:
1,
2,
4,
13,
21,
300
Your objects are strings, not numbers. Try this:
NSArray *myarr = [[NSArray alloc]initWithObjects:#2,#13,#1,#21,#300,#4, nil];
NSSortDescriptor *desc = [[NSSortDescriptor alloc]initWithKey:#"self" ascending:YES];
NSArray *rrrr = [myarr sortedArrayUsingDescriptors:[NSArray arrayWithObject:desc]];
NSLog(#"%#",rrrr);
You're getting an alphabetical sort rather than a numerical sort. See if you get different results with that code instead.

NSArray Sorting

I have an NSArray with values that I am pulling from an NSDictionary using a selector to sort with which has the following values:
John
Brian
Alex
....
Dave
When I use the code below, since they are being compared as strings, the list comes back with:
NSArray *array = [[[self myDictionary] allValues] sortedArrayUsingSelector:#selector(compare:)];
John
Dave
Brian
...
How can I get these values to sort correctly where they are in order 1, 2, 3, etc.? I've looked at several different examples for sorting, but have not been able to find an example like mine. I must also mention that I'm new to objective-c and iOS. Any help would be greatly appreciated.
Thanks!
I was actually able to figure out the solution. I created an NSComparisonResult block using custom logic to read the number portion off of the front of each string and then comparing them numerically:
NSComparisonResult (^sortByNumber)(id, id) = ^(id obj1, id obj2)
{
//Convert items to strings
NSString *s1 = (NSString *)obj1;
NSString *s2 = (NSString *)obj2;
//Find the period and grab the number
NSUInteger periodLoc1 = [s1 rangeOfString:#"."].location;
NSString *number1 = [s1 substringWithRange:NSMakeRange(0, periodLoc1)];
NSUInteger periodLoc2 = [s2 rangeOfString:#"."].location;
NSString *number2 = [s2 substringWithRange:NSMakeRange(0, periodLoc2)];
//Compare the numeric values of the numbers
return [number1 compare:number2 options:NSNumericSearch];
};
Then I sort my array by calling:
NSArray *array = [[[self myDictionary] allValues] sortedArrayUsingComparator:sortByNumber];

Sort a NSMutableArray in objective-c?

I am working on NSMutable Array containing list of "First Name" in it.I want to sort it alphabatically.
I tried this code
NSSortDescriptor * sortFriend = [[[NSSortDescriptor alloc] initWithKey:kfirstName ascending:YES] autorelease];
NSArray * descriptors = [NSArray arrayWithObject:sortFriend];
NSArray * sorted = [Friendsarr sortedArrayUsingDescriptors:descriptors];
correct me if i am wrong.I do have an array of names also if that could be used.
Thanks
I tried the code
NSSortDescriptor * sortFriend = [[[NSSortDescriptor alloc] initWithKey:kfirstName ascending:YES selector: #selector(caseInsensitiveCompare:)] autorelease];
NSArray * descriptors = [NSArray arrayWithObject:sortFriend];
NSArray * arrmp = [temparray sortedArrayUsingDescriptors:descriptors];
But still my result contain 2 'k' chars. one 'k' and 'K'.I want to have case insensitive result
If your NSMutableArray only contains objects of type NSString, simply do:
[myMutableArray sortUsingSelector:#selector(compare:)];
You can sort NSMutable array case insensitively by this code
NSSortDescriptor *sorter=[[[NSSortDescriptor alloc] initWithKey:nil ascending:YES selector:#selector(caseInsensitiveCompare:)]autorelease];
NSArray *sortdescriptor=[NSArray arrayWithObject:sorter];
[cpy_arr_Service_Name sortUsingDescriptors:sortdescriptor];
I found the solution of sorting NSMutableArrays with sample code which can be found on the site below.
http://www.icodeblog.com/2010/12/10/implementing-uitableview-sections-from-an-nsarray-of-nsdictionary-objects/
I hope it help others to as it provides indexed sorting of a grouped table view using an array as the datasource

Creating predicate with pre-built string

Is there a way to create an nspredicate directly from a pre-formatted string without calling predicateWithFormat? The final string would look something like:
(inpatient=1) AND (dischargedate!=<null>) AND ((attending=SMITH) OR (admitting=SMITH) OR (consulting contains[cd] SMITH) OR (attending=JONES) OR (admitting=JONES) OR (consulting contains[cd] JONES))
NSMutableString *preds = [[NSMutableString alloc] initWithString:#""];
NSArray *provs = [self.providerCode componentsSeparatedByString:#"|"];
for (NSString *prov in provs) {
[preds appendFormat:#" (attending=%#) OR (admitting=%#) OR (consulting contains[cd] %#) ", prov, prov, prov];
}
NSString *final = [NSString stringWithFormat:#"(inpatient=%#) AND (dischargedate!=%#) AND (%#)", [NSNumber numberWithBool: self.inpatients], [NSNull null], preds];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:final]];
Yes you can, but you need to modify the format string slightly.
Instead of doing:
[preds appendFormat:#" (attending = %#)", prov];
You'd need to do:
[preds appendFormat:#" (attending = '%#')", prov];
Note the use of single-quotes around the %# modifier. That's how the predicate knows it's a constant value.
However, even if you go this route, you're still stuck using predicateWithFormat:, which you appear to want to avoid. You'll also likely have issues with how you're using NSNull in the format string.
I would recommend doing something more like this:
NSArray *provs = [self.providerCode componentsSeparatedByString:#"|"];
NSMutableArray *providerPredicates = [NSMutableArray array];
NSPredicate *template = [NSPredicate predicateWithFormat:#"attending = $prov OR admitting = $prov OR consulting CONTAINS[cd] $prov"];
for (NSString *prov in provs) {
NSDictionary *substitutions = [NSDictionary dictionaryWithObject:prov forKey:#"prov"];
NSPredicate *p = [template predicateWithSubstitutionVariables:substitutions];
[providerPredicates addObject:p];
}
NSPredicate *final = [NSPredicate predicateWithFormat:#"inpatient = 1 AND dischargedate != nil"];
if ([providerPredicates count] > 0) {
NSPredicate *providers = nil;
if ([providerPredicates count] > 1) {
providers = [NSCompoundPredicate orPredicateWithSubpredicates:providerPredicates];
} else {
providers = [providerPredicates objectAtIndex:0];
}
final = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:final, providers, nil]];
}
This is using a couple different neat things:
Predicate variables. You parse the format string #"attending = $prov OR admitting = $prov OR consulting CONTAINS[cd] $prov" once, and then simply substitute in new values for $prov each time you have a different provider
Constructing compound predicates. You use some class methods on NSCompoundPredicate to turn multiple predicates into a single, grouped OR or AND predicate.

Resources