NSRangeException for empty array except there is an array? - objective-c

I'm having this problem where I keep getting this error in my console:
* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayI objectAtIndex:]: index 0 beyond bounds for empty array'
Here is my code for retrieving the data from the XML document:
CXMLDocument *worldweather = [[CXMLDocument
alloc]initWithContentsOfURL:[NSURL URLWithString:[NSString
stringWithFormat:#"http://free.worldweatheronline.com/feed/weather.ashx?q=%#&format=xml&num_of_days=4&key=0ded69e02b171832121504",query]]
options:0 error:nil];
weathercondition = [[[worldweather nodesForXPath:#"/data/current_condition/weatherIconUrl" error:nil]
objectAtIndex:0] stringValue];
The location that Xcode is using is Williams, CA and the query sent is
Williams+CA
When I plug this into my URL, it works and I get my XML file, but why am I getting this message in my console???
This is driving me crazy. All help would be GREATLY appreciated! Thanks in advance!

Seems that you think that [worldweather nodesForXPath:#"/data/current_condition/weatherIconUrl" error:nil] is NSArray with at least one object inside the array. This is clearly not the case, and you get an error saying that there is no object at index 0, which means that array is empty.
If you are not sure there is at least one object inside an NSArray do not just call objectAtIndex:0.
You could first check how many elements are there in array and then do the work like:
NSArray *weatherArray = [worldweather nodesForXPath:#"/data/current_condition/weatherIconUrl" error:nil];
if ([weatherArray count] > 0){
weathercondition = [[weatherArray objectAtIndex:0] stringValue];
}
If you are not sure what you are getting back from the server, see what is in the array:
NSLog(#"%#", weatherArray);
or check how many elements there are:
NSLog(#"elements in Array: %i", [weatherArray count]);
One additional useful thing you can use is for example [weatherArray lastObject], this will always return the last element of the array and will return nil even if the array is empty (it will not crash like objectAtIndex:0)

Related

Getting "unrecognized selector sent to instance" in code for ios8

This code work in ios7, but I am now getting the error :
-[__NSCFString objectForKeyedSubscript:]: unrecognized selector sent to instance
.m file
//get the JSON response
NSDictionary *jsonData = [NSJSONSerialization
JSONObjectWithData:urlData
options:NSJSONReadingMutableContainers
error:&error];
//Parses the "success" value
success = [jsonData[#"success"] integerValue];
//Was it successful?
if(success){
//successful, save the profile gathered into global gMyProfile
NSArray *profileJSON=jsonData[#"myProfile"];
for (NSDictionary* dict in profileJSON)
{
NSLog(#"First_Name: %#", dict [#"first_name"]);
...
The error is happening on the NSLog statement and from a little research it is complaining about the dict[#"first_name"]);
login.py
....
#Query for user
db_cursor = db.cursor(MySQLdb.cursors.DictCursor)
db_query = """SELECT users.email, users.first_name, users.profile_pic_path, \
FROM users,data WHERE users.email='%s' \
AND users.user_id=data.user_id""" % user_email
db_cursor.execute(db_query)
#If there is one record containing the username check password
if(db_cursor.rowcount == 1):
user_profile = db_cursor.fetchone()
...
json_obj= {'success': 1, 'myProfile': user_profile,}
...
JSON Output:
{'myProfile': {'first_name': 'Matt', 'email': 'matt#email.com', 'profile_pic_path': 'default'}, 'success': 1}
All this code was working, I have not changed anything.
Any help will be greatly appreciated!!!!
dict is not a dictionary. It is a string. Print it and you'll know which string it is.
More likely than not, your JSON is not what you think it is. In particular, the myProfile value is a string instead of a dictionary.
What happens if fetchone() returns None; do you end up with a string in your JSON?
Changed in the .m
//Was it successful?
if(success){
//successful, save the profile gathered into global gMyProfile
NSArray *profileJSON=jsonData[#"myProfile"];
for (NSDictionary* dict in profileJSON)
{
...
to
//Was it successful?
if(success){
//successful, save the profile gathered into global gMyProfile
NSDictionary* dict=jsonData[#"myProfile"];
//no more for loop
...
The python JSON module returns a single dictionary instead of an array of a single dictionary when there is one element. If there are multiple it returns an array of dictionaries.
Still don't know why this didn't give me trouble in ios7 but did in ios8.

Viewing data retrieved from core data stored in an NSArray

I have an iPad app where data is stored in core data. I have used the following code to retrieve the data from the Observations entity which appears to run without any problems and the count of observationList is correct.
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Observations"];
NSError *error = nil;
observationList = [[NSArray alloc]init];
observationList = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
However when I try to access the data with the array - for example:
NSLog(#"%#", [[observationList objectAtIndex:0] objectForKey:#"obsDate"]);
It throws an error
reason: '-[Observations objectForKey:]: unrecognized selector
obsDate exists in core data. Can anyone see what I am doing wrong?
NSManagedObject does not implement objectForKey:, you should be using valueForKey: instead. Your code compiles because the array returns an id so the compiler just has to trust that the method you're calling on it will exist at runtime.
Aside: this line is pointless
observationList = [[NSArray alloc]init];
Because you throw away that array instance on the next line.

Having trouble adding objects to NSMutableArray

Im having truble adding objects to my 2 NSMutableArrays. The data comes from a database and I know that my parsing is correct because I get valid outputs when I use the NSLog. However I can't figur out how to add the 2 different objects to my 2 different NSMutableArrays. Here is my code
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
allDataDictionary = [NSJSONSerialization JSONObjectWithData:webData options:0 error:nil];
feed = [allDataDictionary objectForKey:#"feed"];
arrayOfEntry = [feed objectForKey:#"entry"];
for (NSDictionary *dictionary in arrayOfEntry) {
NSDictionary *title = [dictionary objectForKey:#"title"];
NSString *labelTitle = [title objectForKey:#"label"];
[arrayLabel addObject:labelTitle];
NSDictionary *summary = [dictionary objectForKey:#"summary"];
NSString *labelSummary = [summary objectForKey:#"label"];
[arraySummary addObject:labelSummary]; //This line makes the application crash
}
}
for some reason when I want to add labelSummary to arraySummary I get this error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
Any help is appreciated.
Your parsing is indeed correct. However, when the parser comes across an empty field it returns nil. The problem is the that NSArrays cannot accept nils, because nil is not an object, it's equivalent to 0. Therefore, you most add an object. This the role of NSNull.
Must test to see if the parser returns nil, and if so add [NSNull null].
NSString* labelSummary = [summary objectForKey:#"label"];
[arraySummary addObject:(labelSummary!=nil)?labelSummary:[NSNull null];
The error message tells you that one of the objects you are trying to add to the array is nil.
You have to replace
[arrayLabel addObject:labelTitle];
with
if (labelTitle != nil) {
[arrayLabel addObject:labelTitle];
}
and
[arraySummary addObject:labelSummary];
with
if (labelSummary != nil) {
[arraySummary addObject:labelSummary];
}
If you really need to include a nil object, then use NSNull.

How to deal with an empty object {} in RestKit

The response I sometimes get from the server is a JSON representing an empty object like this {}
I've read this question/answer over here already, which states I should implement the willMapData delegate function and point the *mappableData somewhere else. The thing is I can't figure out what should I assign to *mappableData so that my app won't crash.
I've tried this
- (void)objectLoader:(RKObjectLoader *)loader willMapData:(inout id *)mappableData
{
id<RKParser> parser = [[RKParserRegistry sharedRegistry] parserForMIMEType:RKMIMETypeJSON];
*mappableData = [parser objectFromString:#"{\"unknownObject\":\"\"}" error:nil];
}
But nevertheless my app crashes with a rather pissing
'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]
Can you help me out?
UPDATE
Turning on RKDebug messages gives me this in the console:
Performing object mapping sourceObject: {
}
and targetObject: (null)
then the code reaches RKObjectMapper.m:
if (mappableData) {
id mappingResult = [self performMappingForObject:mappableData atKeyPath:#"" usingMapping:mappingsForContext];
foundMappable = YES;
results = [NSDictionary dictionaryWithObject:mappingResult forKey:#""];
}
but mappingResult over there comes back nil... so the app crashes when it tries to create an NSDictionary with a nil object.
Break up the assignment into two lines.
SomeDataType *object = [parser objectFromString:#"{\"unknownObject\":\"\"}" error:nil];
if(object){
*mappableData = object;
}else{
// You've got nil, do something with it
}
Now you can check for nil values and take the appropriate action. What that action is depends on the context of the crash.

Put Core Data values in an array

I need to put the values retrieved using a Fetch Request from my core data graph into an array, but not entirely sure how to go about this.
I'm using the following to perform the fetch:
NSString *entityName = #"Project"; // Put your entity name here
NSLog(#"Setting up a Fetched Results Controller for the Entity named %#", entityName);
// 2 - Request that Entity
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
// 3 - Filter it if you want
request.predicate = [NSPredicate predicateWithFormat:#"belongsToProject = %#", _selectedProject];
// 4 - Sort it if you want
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"dateTaken"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)]];
// 5 - Fetch it
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
[self performFetch];
As you can see, i'm filtering the values that come back using an NSPredicate.
How would I get these values into an array and also be able to select individual attributes for the entity once they are in the array, for example the project.description or project.name?
Thanks to Eimantas I've got the objects in an array, however I still need to do two things:
Loop through the array and output the data into some HTML
Individually select attributes from the array, for example, the project description.
I'm using the following for loop to do the first:
for (int i=0; i < [projectListArray count]; i++)
{
NSString *tmp = (NSString *)[projectListArray objectAtIndex:i];
}
However, this is returning the error:
-[Project length]: unrecognized selector sent to instance 0x1b9f20
2012-03-28 10:48:35.160 Project App[3973:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Project length]: unrecognized selector sent to instance 0x1b9f20'
It appears as though i might not be incrementing?
[self.fetchedResultsController fetchedObjects] returns the array of fetched objects.
update
It's better to use fast enumaration, not a for loop:
for (Project *project in projectListArray) {
NSString *projectDescription = [project valueForKey:#"description"];
}
You're getting the exception because you're casting an object to NSString while it's a pointer to (I presume) Project managed object.