0

The way I have my program working is it pulls data down into the program via AFHTTPClient. Then I get my response data. I then take this data and parse it into a NSMutableArray via NSJSONSerialization. This array is used to populate a UIPickerView.

This method fires when the user opens the app or presses a refresh button. The problem is when the app opened, the call is made and I get the data back. If I go to the picker it seems empty but when you scroll down the bottom 2 of 5 are in there and when you scroll back up the others get in too. If at any point I press the refresh button the errors go away and the picker is properly populated. Any reason why it is not working properly? I reloadAllComponents after each call is made too.

-(void) getData{
// Paramaters
NSString *lat = @"40.435615";
NSString *lng = @"-79.987872";
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys: lat, @"lat", lng, @"lng", nil];

// posting the data and getting the response
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://mysite.com/"]];
[client postPath:@"/mypostpath.php" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSString *text = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
    NSLog(@"Response: %@", text);

    NSError *error;
    json = [NSJSONSerialization JSONObjectWithData:responseObject options:kNilOptions error:&error];

    // setting the first location to the text feild
    NSDictionary* name = [json objectAtIndex:0];
    locationField.text = [name objectForKey:@"name"];

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"%@", [error localizedDescription]);
}];


// reload the picker
[pickerCust reloadAllComponents];

// setting the first location to the text feild
NSDictionary* name = [json objectAtIndex:0];
locationField.text = [name objectForKey:@"name"];

}

JohnV
  • 285
  • 1
  • 3
  • 13

1 Answers1

1

The problem is because the [pickerCust reloadAllComponents]; is being called before the block that loads the data is finished. Move the call into the success block.

Since it interacts with a UI component, wrap it in an dispatch_async so it runs on the main queue.

dispatch_async(dispatch_get_main_queue(), ^{
    [pickerCust reloadAllComponents];
});
Richard Brown
  • 11,346
  • 4
  • 32
  • 43
  • What exactly does dispatch_async(dispatch_get_main_queue() do differently? – JohnV Mar 13 '13 at 19:53
  • 1
    All updates to the UI are supposed to be made on the main thread. The block is executing on a different thread. the `dispatch_async` will force it's contents to run on the main thread so the UI is updated properly. – Richard Brown Mar 13 '13 at 20:21
  • Thanks! That makes total sense. I'll have to use that from now on. – JohnV Mar 14 '13 at 02:06
  • 1
    The `dispatch_async` to main isn't necessary. AFNetworking completion blocks run on main by default. – mattt Mar 14 '13 at 02:49