简体   繁体   中英

Turning an NSArray of custom objects into a alphabetically sectioned UITableView with an index?

(hmm.. long title)

If I start out with an NSArray of custom objects (each object is a Person) like this:

{
  surname:Allen   forename: Woody,
  surname:Baxter  forename: Stanley,
  surname:Clay    forename: Cassius
}

..etc..

You can see that the array is already in surname order. How do I use that array to create aa UITableView with a section headers A, BC etc, as well as an index thing on the side running vertically

                                                               A
                                                               B
                                                               C

EDIT

I guess what I'm asking is how to turn my array of objects into a Section Array, with all the first letters of the Surnames, and a Surname Array which is perhaps a nested array like this:

{ 
  letter: a
  {  surname:Allen   forename: Woody   }
  letter: b
  {  surname:Baxter  forename: Stanley }
  etc
} 

In fact, perhaps just a nested array will do.

There are probably a million ways of doing this :) Here's one that might work (I am sure it can be done much prettier, but since no one is answering):

NSMutableDictionary *aIndexDictionary = [[NSMutableDictionary alloc] init]; 
NSMutableArray *currentArray;
NSRange aRange = NSMakeRange(0, 1);
NSString *firstLetter;
for (Person *aPerson in personArray) {
  firstLetter = [aPerson.surname substringWithRange:aRange];
  if ([aIndexDictionary objectForKey:firstLetter] == nil) {
    currentArray = [NSMutableArray array];
    [aIndexDictionary setObject:currentArray forKey:firstLetter];
  }
  [currentArray addObject:aPerson];
}

Untested...

Joseph Tura's answer has a number of issues, its untested as he mentioned. Here are the issues:

1) [aPerson.name substringWithRange:aRange] will crash if the name is nil or @"";

2) If firstLetter is already in the list of keys, current array is not reset to point to the array object that belongs to the key firstLetter. So if the currentArray previously pointed to an array whose key in the dictionary is 'K', and yet the current firstLetter being 'P' already existing as a key, the name (that starts with the that letter 'P') will be added to the array of names starting with 'k'. Big issue there.

3) Jassie is added to different array to jassie as a result of difference in the case (uppercase and lowercase 'k' are treated differently).

So, as a huge improvement to Joseph's answer, point number 2 being critical, here is a more accurate implementation for future users:

-(NSDictionary*)indexArrayByName:(NSArray*)people
{
    NSMutableDictionary *anIndexedDict = [[NSMutableDictionary alloc] init];
    NSMutableArray *currentArray = nil;
    NSRange aRange = NSMakeRange(0, 1);
    NSString *firstLetter;

    for(Person *aPerson in people)
    {
        if(aPerson.name.length)
            firstLetter = [[aPerson.name substringWithRange:aRange] uppercaseString];
        else
            firstLetter = @"noName";//find own way to identify these

        if(![anIndexedDict.allKeys containsObject:firstLetter])
        {
            currentArray = [NSMutableArray array];
            anIndexedDict[firstLetter] = currentArray;
        }
        currentArray = anIndexedDict[firstLetter];
        [currentArray addObject:aPerson];
    }    
    return anIndexedDict;
}

Other improvements can be added eg removing leading white spaces etc, but I just thought I'ld mention the main issues. I tested Joseph's answer for those issues, and then mine to make sure they are eliminated :) .Credit to Joseph for main idea. Cheers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM