Sandy Sandy - 4 months ago 11x
iOS Question

How to execute the API method before tableview is loaded?

The requirement is to call edmunds API and display the vendors name in a table as soon as the app launches.

1) -getAPIData()

Retrieves the names of dealers and stores in self.dealerName array.

NSURLSession *session = [NSURLSession sharedSession];
self.task = [session dataTaskWithURL:[NSURL URLWithString:[NSString stringWithFormat:
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (data.length > 0 && error == nil)
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data
self.dealersDictionary = jsonData[@"dealers"];
for (id item in self.dealersDictionary){
if (item[@"name"] != nil){
self.dealerName = item[@"name"];
NSLog(@"could'nt find the names");

2) -viewDidLoad()

This method calls getAPIData(above method).

- (void)viewDidLoad
[super viewDidLoad];
[self getAPIData];

3) -(NSInteger)tableView:(UITableView *)tableview numberOfRowsInSection:(NSInteger)section

Returns the dealers count.

-(NSInteger)tableView:(UITableView *)tableview numberOfRowsInSection:(NSInteger)section
[self.task resume];
return self.dealerName.count;

getAPIData() method is executing after the numberOfRowsInSection() is called. So, the table is rendered empty.

How do I call the getAPIData() before table is loaded on screen?


I believe the problem here is that NSURLSession dataTaskWithURL is asynchronous.

I think you could continue to use an asynchronous method and call [self.tableView reloadData]; after the call returns successfully (e.g., in your completion handler). You could display an activity indicator while you wait for the load to complete.

Or you could make a blocking, synchronous request like so:

// define the URL
NSURL url = [NSURL URLWithString: @""];

// attempt the request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
[request setHTTPMethod: @"GET"];

NSError *reqError;
NSURLResponse *urlResponse;
NSData *returnedData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&reqError];

// parse `returnedData` here

Now you will have your NSData object and you can parse it here the same way you were doing in your completionHandler. This option is viable if you trust that your request response will return quickly.

Final option: use NSURLConnection to perform an async request and use its - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data delegate method to update a UIProgressView for more precise indicator of activity. I would encourage you to look into this method if your request response time is long enough to make the user wonder if anything is happening (e.g., more than a few seconds).