Accessing NSDictionary object outside of ASYNC callback

477 Views Asked by At

I am using UNIRest to make a call and return a JSON object to my app. I have it returning the proper data as a NSDictionary and it logs our perfect. I am now trying to take that data and display it inside of my view. I cannot use my dictionary outside of the callback.

I have been digging around here on StackOverflow for similar results and posts related to variables. I feel it is a scope issue with it being limited to inside of the callback block.

My header file: (UIViewController)

@property (nonatomic, strong) NSDictionary *tideData;

My implementation:

@interface TideDetailViewController ()

@end

@implementation TideDetailViewController

@synthesize tideData;

- (void)viewDidLoad {
    [super viewDidLoad];
     //    tideData = [[NSDictionary alloc] init];


    // location is working, I removed it for testing to call a static string for now

    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
    self.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
    [self.locationManager startUpdatingLocation];

    NSString *locationQueryURL = @"http://api.wunderground.com/api/XXXXXXXXXXXXX/tide/geolookup/q/43.5263,-70.4975.json";
    NSLog(@"%@", locationQueryURL);


    [[UNIRest get:^(UNISimpleRequest *request) {
        [request setUrl: locationQueryURL];
    }] asJsonAsync:^(UNIHTTPJsonResponse *response, NSError *error) {
        // This is the asyncronous callback block
        self.code = [response code];
        NSDictionary *responseHeaders = [response headers];
        UNIJsonNode *body = [response body];
        self.rawResults = [response rawBody];

        // I tried this as self as well
        tideData = [NSJSONSerialization JSONObjectWithData:self.rawResults options: 0 error: &error];

        // this logs perfectly.
        NSLog(@"tideData %@", tideData);

        // tried setting it to the instance
        //self.tideData = tideData;


    }];

    // returns null
    NSLog(@"tideData outside of call back %@", self.tideData);


    // this is where I will be setting label text for now, will refactor once I get it working
   // rest of file contents........

I have tried a good amount of items related to scoping, clearly just missing the mark. Any ideas? I have searched setting global variables, etc. Been stuck on this for a bit now.

Thanks,

Ryan

2

There are 2 best solutions below

1
On

Try setting the object on main thread:

    [self performSelectorOnMainThread:@selector(setTideData:) withObject:[NSJSONSerialization JSONObjectWithData:self.rawResults options: 0 error: &error] waitUntilDone:NO];


- (void)setTideData:(NSDictionary*)dict {
self.tideData = dict;
}
13
On

The reason you see nil is because you are logging it too soon: when you call

NSLog(@"tideData outside of call back %@", self.tideData);

the get:asJsonAsync: method has not received the results yet.

You can fix this problem by adding a setter for your property, and adding some special handling to it, like this:

-(void)setTideData:(NSDictionary*)dict {
    _tideData = dict;
    NSLog(@"tideData outside of call back %@", _tideData);
}

This method will be called from the asynchronous code when you do the tideData = ... assignment.