views:

98

answers:

2

I'm currently trying to implement a UITableView with a delegate and data source that replicates, as closely as possible, the functionality found the ABAddressBookUI framework's ABPeoplePickerNavigationController class, but with the added ability to select multiple contacts at once (as indicated by adding/removing an accessory view to the appropriate UITableViewCell).

Everything is working fine, with the exception of providing localized "section index titles" (the letters that appear in the scroll overlay to the right of the screen) for the UITableView, as should be returned by the data source method:

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView

Obviously, I could just return an NSArray containing the NSStrings A, B, C ...Z, but I'd ideally like this method to return an array of all of the (uppercase, where applicable) letters of the alphabet of the current locale.

One promising lead was:

[[NSLocalecurrentLocale ] objectForKey:@"NSLocaleExemplarCharacterSet" ]

But I can't find any significant documentation on this and it returns an NSCharacterSet, from which I've been unable to extract the actual characters (if I could do that, then NSCharacterSet's capitalizedLetterCharacterSet could also be a promising starting point).

I've also run an otool -tV on the AddressBookUI framework, which revealed a call to the function ABAddressBookCopySectionIndices(), into which an ABAddressBookRef can be passed to obtain exactly what I'm looking for… a CFArray of the localized alphabet. However, it's a private function, so I can't use it in my app.

So, does anybody know whether Cocoa Touch supports this functionality? And, if not, are there any ideas as to how ABAddressBookCopyIndices() is working its magic? I suspect the International Components for Unicode library may well hold the key, but I'm not (as yet) familiar with its capabilities...

+3  A: 

Got bored and wrote this up for you

NSArray * charactersInCharacterSet(NSCharacterSet *charSet)
{
  NSMutableArray * array = [NSMutableArray array];
  NSData * data = [charSet bitmapRepresentation];
  const char* bytes = [data bytes];

  for (int i = 0; i < 8192; ++i)
  {
    if (bytes[i >> 3] & (((unsigned int)1) << (i & 7)))
    {
      [array addObject:[NSString stringWithFormat:@"%C", i]];
    }
  }
  return [NSArray arrayWithArray:array];
}

NSCharacterSet * charSet = [[[[NSLocale alloc] initWithLocaleIdentifier:@"sr_Cyrl_ME"] autorelease] objectForKey:NSLocaleExemplarCharacterSet];
NSArray * chars = charactersInCharacterSet(charSet);
for (NSString *str in chars)
{
  NSLog(@"%@", str);
}

That will give you an array of the characters in the set.

Joshua Weinberg
Please have mercy to East Asians and don't use that :p It'll give a list of thousands of letters, with widely different usage frequencies; if you take every 100th element as the section title, that will select only a very rarely used characters and that'll be totally useless.
Yuji
I didn't really answer the "true" question here. But I answered his subquestion. Your answer is definitely more to the point of what he needs.
Joshua Weinberg
Thanks very much, Josh! Excellent work there. I upvoted this because I'd say it provides some extremely useful functionality, but I hope you don't mind me accepting Yuji's answer instead, as it answers the main question perfectly.
Rich Pollock
No problems :) I actually did some more testing and this fails pretty badly on things like asian character sets. Tried it with a japanese locale and got an empty set back. Would need some love to make it work properly.
Joshua Weinberg
+3  A: 

Please don't assume that the section indices should be "capital letters". That's only valid for some European languages. E.g. Japanese or Chinese don't have the concept of capital letters, they just have too many letters to start with, but there's a customary set of labels usually used in real-world dictionaries or real-world address books.

Instead, use the standard UILocalizedIndexedCollation. It gives exactly what you need.

Yuji
Thanks very much, Yuji! I can't believe I didn't find that class earlier. I Googled so many different phrases to try to find this, but I guess "collation" was the one I needed. I'm aware that capital letters don't exist in a number of languages, which was why I put uppercase in parentheses in the original post. I've now edited it to make that a little clearer. Thanks again.
Rich Pollock
You're perfectly welcome :) Please make an app which nicely works in any language!
Yuji
But now I found this worrying post in SO: http://stackoverflow.com/questions/2909084/localized-index-for-uitableview Apparently the method is there, but was not implemented correctly yet. Gosh.
Yuji
Good find. In that case, there's maybe something more sophisticated going on in ABAddressBookCopySectionIndices(), as I can NSLog() the returned array and it matches exactly what's displayed in the system Address Book. I'll have a play around with UILocalizedIndexedCollation tomorrow and report back (as I guess there's a chance this was fixed in iOS 4).If only we were allowed to use the private APIs!
Rich Pollock
That function probably uses CLDR's 'index characters' as I described here: http://stackoverflow.com/questions/1542781
Steven R. Loomis