Reputation: 81
I am getting data using json with this code and I need to display it in a tableview with two part code and name the problem is writing it all to an array is taking forever and the array comes back null. How can I get each returned element as its own tableview cell? Hundreds of airports are returned.
NSString* path = @"https://api.flightstats.com/flex/airports/rest/v1/json/active?appId=id&appKey=appkey";
NSMutableURLRequest* _request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:path]];
[_request setHTTPMethod:@"GET"];
NSURLResponse *response = nil;
NSError *error = nil;
NSData* _connectionData = [NSURLConnection sendSynchronousRequest:_request returningResponse:&response error:&error];
if(nil != error)
{
NSLog(@"Error: %@", error);
}
else
{
NSMutableDictionary* json = nil;
if(nil != _connectionData)
{
json = [NSJSONSerialization JSONObjectWithData:_connectionData options:NSJSONReadingMutableContainers error:&error];
}
if (error || !json)
{
NSLog(@"Could not parse loaded json with error:%@", error);
}
else
{
NSMutableDictionary *routeRes;
routeRes = [json objectForKey:@"airports"];
for(NSMutableDictionary *flight in routeRes)
{
NSLog(@"ident is %@", [flight objectForKey:@"name"]);
NSString *code=[json objectForKey:@"fs"];
NSString *name=[flight objectForKey:@"name"];
NSLog(@"code %@, name %@", code, name);
[candyArray addObject:[Candy code:code name:name]];
}
}
_connectionData = nil;
NSLog(@"connection done");
The following is the cellForRowatIndex were nothing is shown
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if ( cell == nil ) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Create a new Candy Object
Candy *candy = nil;
// Check to see whether the normal table or search results table is being displayed and set the Candy object from the appropriate array
if (tableView == self.searchDisplayController.searchResultsTableView)
{
candy = [filteredCandyArray objectAtIndex:[indexPath row]];
}
else
{
candy = [candyArray objectAtIndex:[indexPath row]];
}
// Configure the cell
[[cell textLabel] setText:[candy name]];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
return cell;
}
This is a sample of what the returned json is
{"airports":[{"fs":"CLO","iata":"CLO","icao":"SKCL","name":"Alfonso B. Aragon Airport","city":"Cali","cityCode":"CLO","countryCode":"CO","countryName":"Colombia","regionName":"South America","timeZoneRegionName":"America/Bogota","localTime":"2014-03-31T18:51:58.372","utcOffsetHours":-5.0,"latitude":3.543056,"longitude":-76.381389,"elevationFeet":3162,"classification":3,"active":true,"delayIndexUrl":"https://api.flightstats.com/flex/delayindex/rest/v1/json/airports/CLO?codeType=fs","weatherUrl":"https://api.flightstats.com/flex/weather/rest/v1/json/all/CLO?codeType=fs"}
This is the search function:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
// Update the filtered array based on the search text and scope.
// Remove all objects from the filtered search array
[self.filteredCandyArray removeAllObjects];
// Filter the array using NSPredicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name contains[c] %@",searchText];
NSArray *tempArray = [airportsArray filteredArrayUsingPredicate:predicate];
NSLog(@" text %@", searchText);
filteredCandyArray = [NSMutableArray arrayWithArray:tempArray];
NSLog(@"NSLog %@", scope);
}
Upvotes: 0
Views: 1550
Reputation: 45490
What's up with that candy object?
You have an array of dictionnary, here's how you parse that:
Get the array:
NSArray *airportsArray = [json objectForKey:@"airports"];
Set the cell text:
[[cell textLabel] setText:[[airportsArray objectAtIndex:indexPath.row]objectForKey:@"name"]];
[[cell detailTextLabel] setText:[[airportsArray objectAtIndex:indexPath.row]objectForKey:@"code"]];
or for better readability:
NSDictionary *airportAtIndex = [airportsArray objectAtIndex:indexPath.row];
[[cell textLabel] setText:[airportAtIndex objectForKey:@"name"]];
[[cell detailTextLabel] setText:[airportAtIndex objectForKey:@"code"]];
Can you elaborate on how I could use sendAsynch to speed up the process?
Ok, first thing to note, you are not speeding up anything here, the reason why you feel the UI is lagging is because you run the network request on the main thread.
You can solve that problem by sending the request asynchrously, meaning in a background thread which will not freeze your User Interface.
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//this is where you perform the network request
//You can fetch data, in your case get the JSON
dispatch_async(dispatch_get_main_queue(), ^(void){
//in this block you want to manipulate the the User Interface
//this is where you reload the tableView
//or stop an activity indicator
[self.tableView reloadData];
});
});
Things to note (from @HotLicks)
The app must be set up so that the TableView delegate will initially (before the data is downloaded) report zero rows in the section. Then, the reloadData op will cause the TableView to refresh the table. So initially the table will be blank. One could fudge it slightly to initially present a single cell saying "Data is loading" or anything that lets the user know >that an operation is in progress such as a UIActivityIndicator.
read up on Grand Central Dispatch (GCD)
Upvotes: 3
Reputation: 1057
You could take several approaches here in order to improve performance.
Upvotes: 0