来自JSON的数据直接解析为UITableView

时间:2014-03-31 23:56:15

标签: ios objective-c json uitableview

我使用这个代码使用json获取数据,我需要在一个带有两个部分代码的表视图中显示它,并且名称问题是将所有内容写入数组是永远的,并且数组返回null。如何将每个返回的元素作为自己的tableview单元格?返回了数百个机场。

 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");

以下是cellForRowatIndex没有显示

- (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;
}

这是返回的json的样本

{"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"}

这是搜索功能:

- (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);

}

2 个答案:

答案 0 :(得分:3)

那个糖果对象是什么?

你有一系列的字典,在这里你是如何解析的:

获取阵列:

NSArray *airportsArray = [json objectForKey:@"airports"];

设置单元格文本:

[[cell textLabel] setText:[[airportsArray objectAtIndex:indexPath.row]objectForKey:@"name"]];
[[cell detailTextLabel] setText:[[airportsArray objectAtIndex:indexPath.row]objectForKey:@"code"]];

或为了更好的可读性:

NSDictionary *airportAtIndex = [airportsArray objectAtIndex:indexPath.row];
[[cell textLabel] setText:[airportAtIndex objectForKey:@"name"]];
[[cell detailTextLabel] setText:[airportAtIndex objectForKey:@"code"]];

  

您能详细说明如何使用sendAsynch来加速这个过程吗?

好的,首先要注意的是,你在这里加速任何事情,你觉得UI滞后的原因是你在主线程上运行网络请求。

您可以通过异步发送请求来解决该问题,这意味着在后台线程中不会冻结您的用户界面。

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];
    });
});

需要注意的事项(来自@HotLicks

  

必须设置应用程序,以便最初使用TableView委托   (在下载数据之前)在该部分中报告零行。然后,   reloadData操作将导致TableView刷新表。所以   最初表格将为空白。人们可以略微捏造它   最初出现一个单元格说'#34;数据正在加载"或任何让用户知道>正在进行操作的内容,例如UIActivityIndi​​cator。

阅读Grand Central Dispatch (GCD)

答案 1 :(得分:0)

您可以采取多种方法来提高效果。

  1. 在您的申请中尽快开始上传和申请机场。
  2. 互补地尝试在后台线程中执行任何繁重的操作,调度异步操作以构建Candy对象数组。您可以使用dispatch_async。
  3. 另一种方法是使用某种自定义逻辑来避免一次创建整个数组...我会保留例如JSON结果(NSMutableDictionary * routeRes)并按需创建Candy对象(每次单元格都是保持跟踪在JSON中读取/创建的最后一个Candy索引,以完成解析所有字典(然后你可以开始阅读你的糖果数组)....如果糖果创造逻辑不是太重(我认为它不是),那可能会有效。