Reputation: 3
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.
-(void)getAPIData{
NSURLSession *session = [NSURLSession sharedSession];
self.task = [session dataTaskWithURL:[NSURL URLWithString:[NSString stringWithFormat:
@"https://api.edmunds.com/api/dealer/v2/dealers?zipcode=%@&radius=%@&fmt=json&api_key=ycwedw68qast829zx7sn9jnq",
@"01609",@"10"]]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (data.length > 0 && error == nil)
{
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:NULL];
self.dealersDictionary = jsonData[@"dealers"];
for (id item in self.dealersDictionary){
if (item[@"name"] != nil){
self.dealerName = item[@"name"];
NSLog(@"%@",self.dealerName);
}else{
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?
Upvotes: 0
Views: 191
Reputation: 1547
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: @"https://api.edmunds.com/api/dealer/v2/dealers?zipcode=%@&radius=%@&fmt=json&api_key=ycwedw68qast829zx7sn9jnq"];
// attempt the request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:10];
[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).
Upvotes: 0
Reputation: 131481
Short answer: You don't. You display an empty table view, and then in the completion block, you call the tableView's reloadData method and THEN it loads its contents.
Upvotes: 8