Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableView grouping sections from NSMutableArray

I have an app that basically reads an xml file and displays the results in a UITableView. I am trying to group the list items by "country" (an attribute of the xml file elements) and display them in UITableView Sections.

Currently i read the xml file and store each Element as a custom object in an NSMutableArray. The array has the following structure:

Array: 0 => (title, description, date, country) 1 => (title, description, date, country) 2 => (title, description, date, country) 3 => (title, description, date, country)

I have tried creating another array of unique countries which has allowed me to create the section headers correctly but i am struggling to work out a way to display the correct items beneath each section header.

if(![countryArray containsObject:itemCountry]) //if country not already in array
{
   [countryArray addObject:itemCountry]; //Add NSString of country name to array
}

Where itemCountry is the country attribute of each element as i loop through the xml file.

[countryArray count]; //gives me the amount of sections needed

So i guess my question is how do i work out how many rows need to go in each section? How do display the correct array items for each section?

Any help or pointers would be great

like image 379
Leo Avatar asked Jun 18 '11 16:06

Leo


2 Answers

Rather than creating an array of custom objects containing your data, you should look at creating a dictionary.

NSMutableDictionary * theDictionary = [NSMutableDictionary dictionary];

// Here `customObjects` is an `NSArray` of your custom objects from the XML
for ( CustomObject * object in customObjects ) {   
    NSMutableArray * theMutableArray = [theDictionary objectForKey:object.country];
    if ( theMutableArray == nil ) {
        theMutableArray = [NSMutableArray array];
        [theDictionary setObject:theMutableArray forKey:object.country];
    } 

    [theMutableArray addObject:object];
}

/* `sortedCountries` is an instance variable */
self.sortedCountries = [[theDictionary allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

/* Save `theDictionary` in an instance variable */
self.theSource = theDictionary;

Later in numberOfSectionsInTableView:

- (NSInteger)numberOfSectionsInTableView {
    return [self.sortedCountries count];
}

In tableView:numberOfRowsInSection::

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [[self.theSource objectForKey:[self.sortedCountries objectAtIndex:section]] count];
}

In tableView:cellForRowAtIndexPath::

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    [..]

    /* Get the CustomObject for the row */
    NSString * countryName = [self.sortedCountries objectAtIndex:indexPath.section];
    NSArray * objectsForCountry = [self.theSource objectForKey:countryName];
    CustomObject * object = [objectsForCountry objectAtIndex:indexPath.row];

    /* Make use of the `object` */

    [..]
}

This should take you the whole way.

Side Note
If it weren't to present the data and just get the count of the countries then a better alternative to PengOne's approach is to use an NSCountedSet.

NSCountedSet * countedSet = [NSCounted set];
for ( NSString * countryName in countryNames ) {
    [countedSet addObject:countryName];
}

Now all unique countries are available in [countedSet allObjects] and count for each country would be [countedSet countForObject:countryName].

like image 109
Deepak Danduprolu Avatar answered Oct 13 '22 00:10

Deepak Danduprolu


For the section headers using Deepak's answer just go:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return [self.sortedCountries objectAtIndex:section];
}
like image 33
superlogical Avatar answered Oct 13 '22 01:10

superlogical