I push a UIViewController on top of another and in its initwithNib I call a function that loads data from a MySQL database accessed over the internet. I store the results of a database query in an array and use data from that array to change a label on my view. Right now the view loads with "Put text here" in the view rather than the text I want to display. How can I make the view load only after the data is available?
Here's my init:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self){
...setting additional irrelevant attributes....
NSLog(@"running init");
[self fetchFeed: 0]; <----here is where I grab the online data
NSLog(@"%@ SELF TOTAL ARRAY", self.totalArray); <-here is where I try to print the data fetched, but actually this array is still empty when printed even though it's full later.
}
Here's the function to get the data off the internet:
- (void)fetchFeed: (int) type
{
..code to set the request string....
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
/*
NSURLSessionDataTask *dataTask =
[self.session dataTaskWithRequest:req completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error){
*/
static NSURLSession* sharedSessionMainQueue = nil;
if(!sharedSessionMainQueue){
sharedSessionMainQueue = [NSURLSession sessionWithConfiguration:nil delegate:nil delegateQueue:[NSOperationQueue mainQueue]];
}
NSURLSessionDataTask *dataTask =
[sharedSessionMainQueue dataTaskWithRequest:req completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error){
NSMutableArray *jsonObject = [NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
if(type<2) self.totalArray = jsonObject;
// NSLog(@"json object is %@", jsonObject);
dispatch_async(dispatch_get_main_queue(), ^{
[self updateDisplays];
});
}];
[dataTask resume];
}
Here's the function I call inside the dispatch_async block to refresh the data once it's been loaded:
- (void)updateDisplays
{
self.answerArray = [self.totalArray[self.indexLocal] objectForKey:@"answers"];
self.answerIDArray = [self.totalArray[self.indexLocal] objectForKey:@"answerUser"];
self.question.text = [self.totalArray[self.indexLocal] objectForKey:@"question"];
self.questionUser.text = [self.totalArray[self.indexLocal] objectForKey:@"questionUser"];
// NSLog(@"inside update displays");
}
As you can see, I started this using dispatch_async on the default queue then switched to the main queue thinking that would fix the lag, but it didn't. So how can I make the view wait for the data before it displays to the user? I have tried looking over the apple developer documentation for multithreading run loop management, but that seems like more than I need. What am I missing here?
For background, I took a look at some posts on synch vs. async tasks (Understanding dispatch_async) and on how to manage view latency in a uitable view while loading data from the internet (How to stop UITableView from loading until data has been fetched?). The suggestions in these (using the main queue or reloading data in the end of NSURLSession block) did not fix my problem.