Ios 来自JSON数据的分组表视图
我一直在关注YouTube上的一个教程,并试图扩展它的功能。我了解了如何使用GCD将retrieveData方法发送到后台线程,了解了如何使用可达性防止应用程序在飞行模式下崩溃,现在我正尝试将tableview更改为分组样式。几个星期后,我就不知所措了 我想做的是使用键“country”对UITableView进行分组以建立组,并且该国家/地区内的任何城市都会显示在组的单元格中。数据库中的国家数量将发生变化,城市数量也将发生变化 考虑到数据结构,我甚至不确定这是否可行,但如果可行,我可以提出一些建议 JSON数据的结构如下所示:Ios 来自JSON数据的分组表视图,ios,objective-c,json,uitableview,Ios,Objective C,Json,Uitableview,我一直在关注YouTube上的一个教程,并试图扩展它的功能。我了解了如何使用GCD将retrieveData方法发送到后台线程,了解了如何使用可达性防止应用程序在飞行模式下崩溃,现在我正尝试将tableview更改为分组样式。几个星期后,我就不知所措了 我想做的是使用键“country”对UITableView进行分组以建立组,并且该国家/地区内的任何城市都会显示在组的单元格中。数据库中的国家数量将发生变化,城市数量也将发生变化 考虑到数据结构,我甚至不确定这是否可行,但如果可行,我可以提出一些
// you probably want to save these as instance properties
NSMutableArray *countries = [NSMutableArray new];
NSMutableDictionary *citiesForCountries = [NSMutableDictionary new];
for(City *city in citiesArray)
{
NSString *currentCountry = city.country;
NSMutableArray *citiesInCountry = citiesForCountries[@"currentCountry"];
// first city for this country, so add it to our ordered list and create an array to populate with cities
if(! citiesInCountry)
{
[countries addObject:currentCountry];
citiesInCountry = [NSMutableArray new];
citiesForCountries[@"currentCountry"] = citiesInCountry;
}
[citiesInCountry addObject:city];
}
// Then here are some of the relevant methods on how you would use these data structures
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return countries.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *country = countries[section];
NSArray *cities = citiesForCountries[country];
return cities.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
City * cityObject;
NSString *country = countries[indexPath.section];
NSArray *cities = citiesForCountries[country];
cityObject = cities[indexPath.row];
cell.textLabel.text = cityObject.cityName;
cell.detailTextLabel.text = cityObject.cityCountry;
//Accessory
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
[{“id”:“1”,“城市名称”:“伦敦”,“城市州”:“伦敦”,“城市人口”:“8173194”,“国家”:“联合王国”}
以下是.m文件:
#import "CitiesViewController.h"
#import "City.h"
#import "DetailViewController.h"
#import "Reachability.h"
#define getDataUrl @"http://www.conkave.com/iosdemos/json.php"
@interface CitiesViewController ()
@end
@implementation CitiesViewController
@synthesize jsonArray, citiesArray;
- (void)viewDidLoad {
[super viewDidLoad];
//Set the title of our VC
self.title = @"Cities of the World";
//Load data
[self retrieveData];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return citiesArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
City * cityObject;
cityObject = [citiesArray objectAtIndex:indexPath.row];
cell.textLabel.text = cityObject.cityName;
cell.detailTextLabel.text = cityObject.cityCountry;
//Accessory
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
#pragma mark - Navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if ([[segue identifier] isEqualToString:@"pushDetailView"])
{
NSIndexPath * indexPath = [self.tableView indexPathForSelectedRow];
//Get the object for the selected row
City * object = [citiesArray objectAtIndex:indexPath.row];
[[segue destinationViewController] getCity:object];
}
}
#pragma mark -
#pragma mark Class Methods
- (void) retrieveData;
{
Reachability *networkReachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];
if (networkStatus == NotReachable) {
UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"No Internet"
message:@"You must have an internet connection for this feature"
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[message show];
[self.refreshControl endRefreshing];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
return;
}
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
//Retrieve the data asynchronously
dispatch_async(queue, ^{
NSURL * url = [NSURL URLWithString:getDataUrl];
NSData * data = [NSData dataWithContentsOfURL:url];
jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
//Set up our cities array
citiesArray = [[NSMutableArray alloc] init];
//Loop through our jsonArray
for (int i = 0; i < jsonArray.count; i++)
{
//Create our city object
NSString * cID = [[jsonArray objectAtIndex:i] objectForKey:@"id"];
NSString * cName = [[jsonArray objectAtIndex:i] objectForKey:@"cityName"];
NSString * cState = [[jsonArray objectAtIndex:i] objectForKey:@"cityState"];
NSString * cPopulation = [[jsonArray objectAtIndex:i] objectForKey:@"cityPopulation"];
NSString * cCountry = [[jsonArray objectAtIndex:i] objectForKey:@"country"];
//Add the city object to our cities array
[citiesArray addObject:[[City alloc] initWithCityName:cName andCityState:cState andCityCountry:cCountry andcityPopulation:cPopulation andCityID:cID]];
}
//Back to main thread to update UI.use dispatch_get_main_queue() to get main thread
dispatch_sync(dispatch_get_main_queue(), ^{
//Reload our table view
[self.tableView reloadData];
});
});
}
@end
#导入“CitiesViewController.h”
#导入“City.h”
#导入“DetailViewController.h”
#导入“可达性.h”
#定义getDataUrl@“http://www.conkave.com/iosdemos/json.php"
@接口CitiesViewController()
@结束
@CitiesViewController的实现
@综合jsonArray、citiesArray;
-(无效)viewDidLoad{
[超级视图下载];
//设置我们VC的标题
self.title=@“世界城市”;
//加载数据
[自检索数据];
}
-(无效)未收到记忆警告{
[超级记忆警告];
//处置所有可以重新创建的资源。
}
#pragma标记-表视图数据源
-(NSInteger)表格视图中的节数:(UITableView*)表格视图{
//返回节数。
返回1;
}
-(NSInteger)表视图:(UITableView*)表视图行数节:(NSInteger)节{
//返回节中的行数。
返回citiesArray.count;
}
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
静态NSString*CellIdentifier=@“Cell”;
UITableViewCell*单元格=[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//配置单元格。。。
城市*城市对象;
cityObject=[CitieArray对象索引:indexath.row];
cell.textlab.text=cityObject.cityName;
cell.detailTextLabel.text=cityObject.cityCountry;
//附属品
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
返回单元;
}
#pragma标记-导航
-(void)prepareForSegue:(UIStoryboardSegue*)segue发送方:(id)发送方{
//使用[segue destinationViewController]获取新的视图控制器。
//将选定对象传递给新的视图控制器。
if([[segue identifier]isEqualToString:@“pushDetailView”])
{
NSIndexPath*indexPath=[self.tableView indexPathForSelectedRow];
//获取所选行的对象
City*object=[CitieArray objectAtIndex:indexPath.row];
[[segue destinationViewController]获取城市:对象];
}
}
#布拉格标记-
#pragma标记类方法
-(无效)检索数据;
{
可达性*网络可达性=[Reachability Reachability For InternetConnection];
NetworkStatus NetworkStatus=[networkReachability currentReachabilityStatus];
if(网络状态==不可访问){
UIAlertView*消息=[[UIAlertView alloc]initWithTitle:@“无互联网”
消息:@“您必须具有此功能的internet连接”
代表:赛尔夫
取消按钮:@“确定”
其他按钮:无];
[信息显示];
[自我刷新控制结束刷新];
[UIApplication sharedApplication].networkActivityIndicatorVisible=否;
回来
}
调度队列=调度获取全局队列(调度队列优先级高,0ul);
//异步检索数据
调度异步(队列^{
NSURL*url=[NSURL URLWithString:getDataUrl];
NSData*data=[NSData dataWithContentsOfURL:url];
jsonArray=[NSJSONSerialization JSONObjectWithData:数据选项:针织错误:nil];
//建立我们的城市阵列
CitieArray=[[NSMutableArray alloc]init];
//循环浏览我们的jsonArray
for(int i=0;i
您可以通过几种方法轻松地对数据进行分组。一种方法是使用数组对国家进行排序,并使用字典对其中的城市进行分组
创建完城市
对象后,可以执行以下操作:
// you probably want to save these as instance properties
NSMutableArray *countries = [NSMutableArray new];
NSMutableDictionary *citiesForCountries = [NSMutableDictionary new];
for(City *city in citiesArray)
{
NSString *currentCountry = city.country;
NSMutableArray *citiesInCountry = citiesForCountries[@"currentCountry"];
// first city for this country, so add it to our ordered list and create an array to populate with cities
if(! citiesInCountry)
{
[countries addObject:currentCountry];
citiesInCountry = [NSMutableArray new];
citiesForCountries[@"currentCountry"] = citiesInCountry;
}
[citiesInCountry addObject:city];
}
// Then here are some of the relevant methods on how you would use these data structures
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return countries.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *country = countries[section];
NSArray *cities = citiesForCountries[country];
return cities.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
City * cityObject;
NSString *country = countries[indexPath.section];
NSArray *cities = citiesForCountries[country];
cityObject = cities[indexPath.row];
cell.textLabel.text = cityObject.cityName;
cell.detailTextLabel.text = cityObject.cityCountry;
//Accessory
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
谢谢。不过有几个问题。你说“创建完城市对象后…”我不确定您引用的确切位置。City是一个类,对象是在City.h和City.m文档中创建的,但它似乎不是您发布代码的正确位置。其次,我收到关于在本地声明变量的警告,以及一个错误,上面写着“country”在类型为City的对象上找不到。如果我好像迷路了,很抱歉-我迷路了。我指的地方是在您完成后立即在您的
retrieveData
方法中