NSInvalidArgumentException when using a value extracted from JSON data - iphone

I am trying to retrieve value for id:
{"id":1,"name":"XYZ"}
When I use:
NSString *jsonData = [[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
NSArray * myPeople = [jsonData JSONValue];
NSString *name = [[NSString alloc] init];
NSDictionary *person = [myPeople objectAtIndex:[indexPath row]];
name = [NSString stringWithString:[person valueForKey:#"id"]];
name = [name stringByAppendingString:#". "];
name = [name stringByAppendingString:[person valueForKey:#"name"]];
name = [name stringByAppendingString:[person valueForKey:#"id"]];
cell.textLabel.text = name;
I get the following error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException'
reason: '-[NSCFNumber length]: unrecognized selector sent to instance 0x4e7f8b0
How can I fix this?

You are calling both stringWithString: and stringByAppendingString: but then passing in an NSNumber
You need to get the string value of the NSNumber
[[person valueForKey:#"id"] stringValue];
or use a format like:
name = [NSString stringWithFormat:#"%#%#", name, [person valueForKey:#"id"]];
I would also consider changing the structure slightly to make it easier to follow like this:
NSDictionary *person = [myPeople objectAtIndex:[indexPath row]];
NSString *personName = [person valueForKey:#"name"];
NSSNumber *personId = [person valueForKey:#"id"];
NSString *name = [NSString stringWithFormat:#"%#. %# %#", personId, personName, personId];
For sorting you want to make sure you are not pulling that data every time you set up a cell (looks like you are) or it will be a terrible experience.
I'm sure someone can point you to a better way of sorting but the quickest thing I can think of is
NSArray *myPeople = [[jsonData JSONValue] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [[obj1 objectForKey:#"id"] compare:[obj2 objectForKey:#"id"]];
}]

Related

Getting crashed when NSdictionary or NSString values into UILABEL

-(void) httpDataDidFinishLoadingWithData:(NSData *)theData
{
m_activityLoaded=NO;
temp=[[NSString alloc] initWithData:[dataLoader httpData]
encoding:NSUTF8StringEncoding];
NSLog(#"TEMP IS TEMP %#", temp);
NSDictionary *dict = [[NSDictionary alloc]init];
dict = [[temp JSONValue] objectForKey:#"location"];
NSDictionary *dict1 = [[NSDictionary alloc]init];
dict1 = [[temp JSONValue] objectForKey:#"wind"];
NSDictionary *dict2 = [[NSDictionary alloc]init];
dict2 = [dict1 objectForKey:#"direction"];
NSDictionary *dict3 = [[NSDictionary alloc]init];
dict3 = [[temp JSONValue] objectForKey:#"atmosphere"];
NSDictionary *dict4 = [[NSDictionary alloc]init];
dict4 = [[temp JSONValue] objectForKey:#"condition"];
NSDictionary *dict5 = [[NSDictionary alloc]init];
dict5 = [dict4 objectForKey:#"text"];
NSDictionary *dict6 = [[NSDictionary alloc]init];
dict6 = [dict4 objectForKey:#"code"];
NSDictionary *dict7 = [[NSDictionary alloc]init];
dict7 = [dict4 objectForKey:#"temperature"];
temperatureLabel.text = [dict4 objectForKey:#"temperature"];
}
Crash occurs at temperatureLabel.text = [dict4 objectForKey:#"temperature"];
I dont know man, Data is exactly printed in the console, but crashing at UILABEL(temperatureLabel). Help me out, thanks in advance
if you look at the error you are getting it is telling you that the object return for the key temperature is not a NSString or NSDictionary but a NSNumber.
Give this a try:
-(void) httpDataDidFinishLoadingWithData:(NSData *)theData {
m_activityLoaded=NO;
temp=[[NSString alloc] initWithData:[dataLoader httpData]
encoding:NSUTF8StringEncoding];
NSLog(#"TEMP IS TEMP %#", temp);
NSDictionary *dict = [[temp JSONValue] objectForKey:#"location"];
NSDictionary *dict1 = [[temp JSONValue] objectForKey:#"wind"];
NSDictionary *dict2 = [dict1 objectForKey:#"direction"];
NSDictionary *dict3 = [[temp JSONValue] objectForKey:#"atmosphere"];
NSDictionary *dict4 = [[temp JSONValue] objectForKey:#"condition"];
NSDictionary *dict5 = [dict4 objectForKey:#"text"];
NSDictionary *dict6 = [dict4 objectForKey:#"code"];
NSNumber *temperature = [dict4 objectForKey:#"temperature"];
temperatureLabel.text = [NSString stringWithFormat:#"%#", temperature];
}
You might want to look at NSNumberFormatter for formatter the temperature with something like: °F or °C.
Are you sure that your object is of NSString class?
Try putting in something like:
if([[dict4 objectForKey:#"temperature"] isKindOfClass:[NSString class]])
NSLog(#"lalala");
If it does not get logged to the console it means that your object is not an NSString and you could try something like:
temperatureLabel.text = [NSString stringWithFormat:#"%#", [dict4 objectForKey:#"temperature"]];
You should change the %# according to the kind of object you have stored in your dictionnary.
Your dictionary contains an NSNumber instance and you are assigning that to a property of type NSString. The crash message is your tip off there. Use stringValue or some other way to get the number's data into string form.

sending NSDictionary with openURL

I want to open an other application using
[[UIApplication sharedApplication]openURL:[[NSURL alloc]initWithString:myString]];
as log as myString is like
NSString *myString=[NSString stringWithFormat:#"testHandleOpenUrl://?%#",#"123"];
it works fine but if I try to use an NSDictionary like
NSString *myString=[NSString stringWithFormat:#"testHandleOpenUrl://?%#",userInfo];
it fails without an error
Hope you can help me.
Try enumerating all the elements in your dictionary and appending those to your URL.
NSMutableString *params = [[[NSMutableString alloc] init] autorelease];
NSEnumerator *keys = [userInfo keyEnumerator];
NSString *name = [keys nextObject];
while (nil != name) {
[params appendString: name];
[params appendString: #"="];
[params appendString: [userInfo objectForKey:name]];
name = [keys nextObject];
if (nil != name) {
[params appendString: #"&"];
}
}
NSString *myString=[NSString stringWithFormat:#"testHandleOpenUrl://?%#",params];
When you use an NSDictionary in the format string, you get a URL that looks like this:
testHandleOpenUrl://?{
bar = foo;
}
The result of calling -description on userInfo is simply substituted for the %#. Presumably, you want to pass parameters contained in the dictionary in the URL. Probably something like this:
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:#"bar", #"foo", nil];
NSString *myString=[NSString stringWithFormat:#"testHandleOpenUrl://?foo=%#", [userInfo objectForKey:#"foo"]];
NSLog(#"myString: %#", myString); // prints "myString: testHandleOpenUrl://?foo=bar"
NSString * paramString = #"";
int i = 0;
for(NSString * key in [userInfo allKeys]){
NSString * value = (NSString*)[userInfo objectForKey:key];
NSString * valueParam = [NSString stringWithFormat:#"%#%#=%#",(i==0)?#"?":#"&",key,value];
paramString = [paramString stringByAppendingString:valueParam];
i++;
}
NSString *myString=[NSString stringWithFormat:#"testHandleOpenUrl://%#", paramString];

Problem with UISearchBar and NSMutableArray

I have a tableview with a search bar. I want to search my whole core data database.
I loaded everything into an array here:
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Entity" inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
NSError *error = nil;
NSArray *array = [managedObjectContext executeFetchRequest:request error:&error];
self.myArray = array;
I'm then searching using this method but getting an error:
- (void) searchTableView {
NSString *searchText = searchBar.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
for (NSDictionary *dictionary in myArray)
{
NSString *value = [dictionary objectForKey:#"name"];
[searchArray addObject:value];
}
for (NSString *sTemp in searchArray)
{
NSRange titleResultsRange = [sTemp rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
[copyListOfItems addObject:sTemp];
}
[searchArray release];
searchArray = nil;
}
But when I search, I get the crash here:
MedicalCode *code = [self.copyListOfItems objectAtIndex:indexPath.row];
cell.codeLabel.text = code.description;
Error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ICD9Disease objectForKey:]: unrecognized selector sent to instance 0x1be6e0'
You are getting the error because you are asking for an object, but you're trying to set a string, in the line:
NSString *value = [dictionary objectForKey:#"name"];
Since you're getting a string, not an object, what you need to use is valueForKey:
NSString *value = [dictionary valueForKey:#"name"];
It looks like you're expecting the fetch request to return dictionaries, but it's actually returning instances of the class ICD9Disease.

NSMutableDictionary confused over how to use keys with certain code?

I'm getting data from a database and I need to add the string field value and the record id.
However, I need this to work with some existing code...
I'm replacing this (see code below) and getting data from my database.
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.allCategories = dict;
[dict release];
This is the file it loads...
But needs to work with these key and value search functions.
- (void)resetSearch {
NSMutableDictionary *allCategoriesCopy = [self.allCategories mutableDeepCopy];
self.Categories = allCategoriesCopy;
[allCategoriesCopy release];
NSMutableArray *keyArray = [[NSMutableArray alloc] init];
[keyArray addObject:UITableViewIndexSearch];
[keyArray addObjectsFromArray:[[self.allCategories allKeys]
sortedArrayUsingSelector:#selector(compare:)]];
self.keys = keyArray;
[keyArray release];
}
.
- (void)handleSearchForTerm:(NSString *)searchTerm {
NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init];
[self resetSearch];
for (NSString *key in self.keys) {
NSMutableArray *array = [Categories valueForKey:key];
NSMutableArray *toRemove = [[NSMutableArray alloc] init];
for (NSString *name in array) {
if ([name rangeOfString:searchTerm
options:NSCaseInsensitiveSearch].location
== NSNotFound)
[toRemove addObject:name];
}
if ([array count] == [toRemove count])
[sectionsToRemove addObject:key];
[array removeObjectsInArray:toRemove];
[toRemove release];
}
[self.keys removeObjectsInArray:sectionsToRemove];
[sectionsToRemove release];
[table reloadData];
}
Keep getting an error from this code...
NSDictionary *arrayTmp= [[NSDictionary alloc] init];
... loop records
int cid = sqlite3_column_int(statementTMP, 0);
NSString *category = [[NSString alloc]
initWithUTF8String:(char *)sqlite3_column_text(statementTMP, 1)];
[arrayTmp setObject:category forKey:[NSString stringWithFormat:#"%i", cid]];
Error caused by line above
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString count]: unrecognized selector sent to instance 0x4d4c500' * Call stack at first throw *
... end loop
self.allCategories = arrayTmp;
[arrayTmp release];
The error message says you are sending 'count' to an instance of NSString.
My guess is that the plist at 'path' (the plist file) has a string as one of the values. As you iterate through 'Categories' you expect each value to be an array (i.e. 'NSMutableArray *array = [Categories valueForKey:key];') and send that value a 'count' message.
One of the objects you expect to be an array is a string.
setValue is key-value coding method. You should use setObject:forKey: instead.
arrayTmp should be inited with [[NSMutableDictionary alloc] init].
First of all, you're using wrong method:
[arrayTmp setValue:category forKey:[NSString stringWithFormat:#"%i", cid]];
which method used for key-value coding (you can find more about KVO here).
The method you're looking for is:
[arrayTmp setObject:category forKey:[NSString stringWithFormat:#"%i", cid]];
Moreover, you should NSMutableDictionary. The NSDictionary you're using does not support mutation. (you can find more info on NSMutableDictionary here).
Cheers,
Pawel

NSCFString countByEnumeratingWithState:objects:count: ERROR while searching NSMutableArray

I have the following situation where
I have an NSMutableArray filled with an xml file which I want to search.
When I enter something in the search field I get this Error:
-[NSCFString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x5b388b0
What does it means and how can I fix it??
I suppose the error is somewhere around here.
- (void)searchTableView{
searchedList = [[NSMutableArray alloc] init];
NSLog(#"new list %#", searchedList);
NSString *searchText = searchBar.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
for (NSDictionary *dictionary in list) {
NSArray *array = [dictionary objectForKey:#"TITLE"];
[searchArray addObjectsFromArray:array];
}
for (NSString *TempArray in searchArray) {
NSRange titleResults = [TempArray rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResults.length > 0)
[searchedList addObject:TempArray];
}
[searchArray release];
searchArray = nil;
}
it means you are calling a method designed for an NSArray (countByEnumeratingWithState:objects:count on a NSString.
I don't know ifthis code is copy/paste from yours, but if so, at the end where you use [searchList addObject:TempArray] you don't have an object named searchList.
Also, work on your naming conventions. big time.