从 JSON 解析数据直接到 UITableView
Posted
技术标签:
【中文标题】从 JSON 解析数据直接到 UITableView【英文标题】:Data from JSON Parsing straight to UITableView 【发布时间】:2014-03-31 23:56:14 【问题描述】:我正在使用带有此代码的 json 获取数据,我需要在包含两部分代码的 tableview 中显示它,并将其命名为问题是将其全部写入数组需要永远并且数组返回 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);
【问题讨论】:
它所占用的一些“永远”是由于应用程序在请求运行时阻塞了主线程。您需要使用 sendAsnych 解决此问题。但在此之前,请检查您是否正在取回数据。 NSLog(@"开始");在发送请求之前,和 NSLog(@"json=%@", json);在 JSON 解析之后。 好吧,你需要告诉我们 JSON 是什么样子的。 我将它添加到我的帖子中,但值正在返回 NSLog(@"code %@, name %@", code, name);我需要弄清楚如何将这些信息放在 tableview 中。 我认为没有任何真正需要拥有您的 Candy 对象。只需将“飞行” NSDictionary 对象添加到您的 NSArray 并直接使用它们。 您发布的 JSON 与您尝试反汇编的 JSON 不同。我在任何地方都没有看到包含“机场”的字典,并且代码不承认数组的存在,而实际上航班被包含在数组中。 【参考方案1】:那个糖果是怎么回事?
你有一个字典数组,下面是你如何解析它:
获取数组:
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 刷新表。所以 最初该表将为空白。可以稍微捏造一下 最初显示一个单元格,说“数据正在加载”或任何让用户知道>操作正在进行的内容,例如 UIActivityIndicator。
阅读Grand Central Dispatch (GCD)
【讨论】:
您能否详细说明我如何使用 sendAsynch 来加快进程? @user1828081 我扩展了我的答案 应该注意,必须设置应用程序,以便 TableView 委托最初(在下载数据之前)报告该部分中的零行。然后,reloadData
操作将导致 TableView 刷新表。所以最初表格是空白的。可以稍微捏造一下,以首先显示一个单元格,说“数据正在加载”或其他任何内容。
@HotLicks 是的,完全正确,我试图在 cmets 中展示,可能不太清楚,我会再编辑一点。
感谢您的帮助!抱歉,我还有一个问题,我的搜索功能不起作用(添加到问题中)我假设我错过了一些基于更改数据检索和显示方式的愚蠢的东西。【参考方案2】:
您可以在这里采取多种方法来提高性能。
-
尽快在您的应用程序中开始上传和请求机场。
免费尝试在后台线程中执行任何繁重的操作,调度异步操作来构建 Candy 对象数组。您可以使用 dispatch_async。
另一种方法是使用某种自定义逻辑来避免一次创建整个数组……例如,我将保留 JSON 结果 (NSMutableDictionary *routeRes) 并按需创建 Candy 对象(每次一个单元格必需),跟踪在 JSON 中读取/创建的最后一个 Candy 索引,以完成对所有字典的解析(然后您可以开始读取您的糖果数组)……。如果 Candy 创建逻辑不太重(我认为不是),这可能会起作用。
【讨论】:
以上是关于从 JSON 解析数据直接到 UITableView的主要内容,如果未能解决你的问题,请参考以下文章
Android:如何让我检索到的(来自 mysql)JSON 解析数据添加到 ListView 每分钟刷新一次