1

I'm getting started with Objective-C, and can't seem to extract the data being pulled by AFNetworking to use as label text, etc. I'm using it for a weather app backed by Forecast.io, and the Forecastr API wrapper. If the API is writing the JSON to a dictionary, I can't seem to find it.

In the main view controller:

[forecastr getForecastForLocation:location time:nil exclusions:nil success:^(id JSON) {
        NSLog(@"JSON response was: %@", JSON);
        NSLog(@"Testing: %@", [JSON valueForKey:kFCSummary]);

    } failure:^(NSError *error, id response) {
        NSLog(@"Error while retrieving forecast: %@", [forecastr messageForError:error withResponse:response]);
    }];
}

The first NSLog line will return the full JSON object, serialized and everything, but the second one just puts out NULL.

In the Forecastr.m file:

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
if (self.callback) {
    AFHTTPRequestOperation *httpOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    [httpOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSString *JSONP = [[NSString alloc] initWithData:responseObject encoding:NSASCIIStringEncoding];
        if (self.cacheEnabled) [self cacheForecast:JSONP withURLString:cacheKey];
        success(JSONP);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        failure(error, operation);
    }];
    [pendingRequests addObject:httpOperation];
    [forecastrQueue addOperation:httpOperation];
} else {
    AFJSONRequestOperation *jsonOperation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
        success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        if (self.cacheEnabled) [self cacheForecast:JSON withURLString:cacheKey];
        success(JSON);
    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON){
        failure(error, JSON);
    }];
    [pendingRequests addObject:jsonOperation];
    [forecastrQueue addOperation:jsonOperation];
}

I can tell that this reading for a cached forecast, and then pulling down a new JSON file if the cache is too old. But I can't tell where it's putting the JSON, and it's not in a dictionary which is how most tutorials and resources use.

I've tried a bunch of different things already, such as creating my own dictionary, but it won't add the JSON object in there. I've also tried to use the returned JSON object as a dictionary and a key-value pair, but nothing seems to be working. I've been banging my head against the wall for days, but there's hardly anyone out there using Forecastr with a problem.

iwasrobbed
  • 46,496
  • 21
  • 150
  • 195
Luke Patton
  • 63
  • 1
  • 8
  • Change log to NSLog(@"JSON response was: %@",NSStringFromClass( [JSON class])); and tell us what it says. If you get a string, you're probably configuring your call to the library incorrectly. If you get a dictionary your key is probably wrong. – Wain Jun 16 '13 at 08:48
  • That returned: "JSON response was: __NSCFDictionary". Does that mean that the JSON is being stored in a NSDictionary of some type? I searched around for NSCFDictionary and can see that it's a private subclass, but I can't find out how to use it. Using @"Test: %@", [JSON objectForKey:kFCTemperature still returns a null value. – Luke Patton Jun 16 '13 at 14:13
  • Yes. It could just be that the temperature isn't available (like it says can happen in the docs). You haven't provided the JSON response so I can't say much more. – Wain Jun 16 '13 at 15:56
  • I've put what get's logged in a [gist](https://gist.github.com/lkpttn/5792589). Even using the exact methods described in the documentation, it's still returning a null value. – Luke Patton Jun 16 '13 at 16:41

2 Answers2

1

The problem is that the data you are getting back is split into a number of different sections (such as the current day and each of the days of the week). You can't just ask the overall data set for the temperature, you need to navigate to the 'day' that you're interested in and then request the temperature. Such as:

[[JSON objectForKey:kFCCurrentlyForecast] objectForKey:kFCTemperature]
Wain
  • 118,658
  • 15
  • 128
  • 151
  • This sounds like it's right on the cusp, but I'm still a little too incompetent to figure it out. I tried using `[kFCCurrentlyForecast valueForKey:kFCTemperature];` to set some label text, but it threw an exception. `2013-06-16 14:55:37.773 WeatherBud[71223:c07] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFConstantString 0x412c0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key temperature.'` – Luke Patton Jun 16 '13 at 18:57
  • `kFCCurrentlyForecast` and `kFCTemperature` are both string constants that you can use only as keys to access data in dictionaries. `JSON` is you dictionary which contains other dictionaries (and arrays). The line you've pasted in your comment isn't the same as the line in my answer. Why are you trying to use a key as a dictionary? – Wain Jun 16 '13 at 21:26
  • I wasn't sure how to navigate to the correct dictionary. But I just retried it using your method and it worked! Thank you so much, I'll accept your answer. – Luke Patton Jun 16 '13 at 21:42
0

JSON seems to be a string (github). In order to parse this, you can use a library such as JSONKit.

blake305
  • 2,196
  • 3
  • 23
  • 52
  • Or just use the built-in `NSJSONSerialization` class. –  Jun 16 '13 at 05:16
  • Is JSONP not the cached JSON object? In the view controller, it's reading it from the JSON id. I'll try JSONKit, it's already been serialized because the console log is readable and formatted. – Luke Patton Jun 16 '13 at 05:41
  • He's not requesting it as JSONP, he's requesting it as JSON so it's being returned as a serialized object already. There is a `callback` property to set in Forecastr if it's a JSONP request. (I wrote Forecastr) – iwasrobbed Jun 17 '13 at 17:37