我一直在关注YouTube上的教程并尝试扩展其功能。我想出了如何使用GCD将retrieveData方法发送到后台线程,想出了如何使用Reachability来防止应用程序在飞行模式下崩溃,现在我正在尝试将tableview更改为分组样式。几个星期后,我才结束了。
我想要做的是使用关键字“country”对UITableView进行分组以建立组,并且该国家/地区内的任何城市都会显示在组的单元格中。数据库中的国家数量以及城市数量都将发生变化。
我甚至不确定数据结构是否可行,但如果是,我可以使用一些建议。
JSON数据的结构如下:
[{“id”:“1”,“cityName”:“London”,“cityState”:“London”,“cityPopulation”:“8173194”,“country”:“United Kingdom”}
这是.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
答案 0 :(得分:0)
您可以通过几种方式轻松地对数据进行分组。一种方法是使用数组来排序国家,使用字典对其中的城市进行分组。
完成City
个对象的创建后,您可以执行以下操作:
// 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;
}