Reputation: 712
I'm starting out with JSON (totally new to web services) and am doing this to collect the data from the Wunderground API. This -synchronous- code works for me:
NSDictionary *weatherData;
NSString *urlString;
if (self.apiKey) {
urlString = [@"http://api.wunderground.com/api/" stringByAppendingString:self.apiKey];
}
urlString = [urlString stringByAppendingString:@"/conditions/q/CA/San_Francisco.json"];;
NSURL *url = [NSURL URLWithString:urlString];
NSData *jasonData = [NSData dataWithContentsOfURL:url];
NSError *error;
weatherData = [NSJSONSerialization JSONObjectWithData:jasonData options:0 error:&error];
if (error) {
NSLog(@"Error creating JSON Object, error description = %@", [error localizedDescription]);
}
return weatherData;
// returns a dictionary
But this doesn't:
__block NSDictionary *weatherData;
dispatch_queue_t weatherDataQueue = dispatch_queue_create("weatherDataQueue", NULL);
dispatch_async(weatherDataQueue, ^{
NSString *urlString;
if (self.apiKey) {
urlString = [@"http://api.wunderground.com/api/" stringByAppendingString:self.apiKey];
}
urlString = [urlString stringByAppendingString:@"/conditions/q/CA/San_Francisco.json"];;
NSURL *url = [NSURL URLWithString:urlString];
NSData *jasonData = [NSData dataWithContentsOfURL:url];
NSError *error;
weatherData = [NSJSONSerialization JSONObjectWithData:jasonData options:0 error:&error];
if (error) {
NSLog(@"Error with creating JSON Object, error description %@", [error localizedDescription]);
}
});
NSLog(@"weatherData = %@", weatherData);
return weatherData;
// returns NULL
Now, I realize that this probably has to do with the fact that when I return weatherData
, the code in the dispatched block hasn't run yet.
I would greatly appreciate it if anybody could help me figure out how to fix this.
Upvotes: 0
Views: 175
Reputation: 1740
I would suggest posting a NSNotification and then set up a listener for that notification and execute the necessary code on weatherData at that point.
Though I do like @bbum suggestion the best.
Upvotes: 0
Reputation: 4607
May I give a suggestion that will simplify your life greatly - use AFNetworking for network operations such as this.
Alternatively you need to pass in a callback block to your function that can then execute with the weatherData
value. Your assumption regarding the weatherData
error is correct.
Upvotes: 0
Reputation: 162712
When doing something asynchronously, you need to trigger the "hey, I've downloaded the data!" from the asynchronously executing code.
That is, the end of your block that loads data would do something like:
dispatch_async(dispatch_get_main_queue(), ^{
... do whatever is necessary to load/display the data in the UI here ...
});
Upvotes: 4