从JSON数据分组的Tableview

时间:2015-03-14 19:18:31

标签: ios objective-c json uitableview

我一直在关注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

1 个答案:

答案 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;
}