Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Since it looks like no one could offer up a solution, I thought I would post the solution I came up with. First, I created a model for my data:</p> <pre><code>@interface MyModel : NSObject { NSString* _value; NSString* _sortableValue; } @property (nonatomic,copy) NSString* value; - (NSString*)sortableValue; - (NSString*)comparableString:(NSString*)str; @end </code></pre> <p>They key to the model is the comparableString method, which gets used to create the sortableValue. Here's the implementation of the model:</p> <pre><code>@implementation MyModel @synthesize value=_value; -(void)dealloc { [_value release]; [_sortableValue release]; [super dealloc]; } - (void)setValue:(NSString*)value { [_value release]; _value = [value copy]; [_sortableValue release]; _sortableTValue = nil; } - (NSString*)sortableValue { if (_sortableValue == nil) _sortableValue = [[self comparableString:_value] retain]; return _sortableValue; } - (NSString*)comparableString:(NSString*)str { if (str == nil) return nil; else if ([str length] == 0) return [NSString stringWithString:str]; NSCharacterSet* numbersSet = [NSCharacterSet decimalDigitCharacterSet]; if ([str rangeOfCharacterFromSet:numbersSet options:0 range:NSMakeRange(0, 1)].location != NSNotFound) return [NSString stringWithString:str]; NSRange range = NSMakeRange(0, [str length]); if ([str compare:@"a " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 2)] == NSOrderedSame) range.location = 2; else if ([str compare:@"an " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 3)] == NSOrderedSame) range.location = 3; else if ([str compare:@"the " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 4)] == NSOrderedSame) range.location = 4; range.length -= range.location; NSCharacterSet* lettersSet = [NSCharacterSet letterCharacterSet]; NSUInteger letterOffset = [str rangeOfCharacterFromSet:lettersSet options:0 range:range].location; if (letterOffset == NSNotFound) return [NSString stringWithString:str]; letterOffset -= range.location; range.location += letterOffset; range.length -= letterOffset; return [str substringWithRange:range]; } @end </code></pre> <p>In addition to the removing the leading articles from the string, it also removes any leading non-letter characters. I have a song in my iPod library entitled "$ell Your $oul", which ends up in the E section in the MPMediaPickerController. I'm not sure that's what I would have done had I crated the initial sorting algorithm, but I was going to consistency with the MPMediaPickerController, so there you go.</p> <p>The final piece of the puzzle is the UILocalizedIndexedCollation class. This handy little helper class will help you sort your data to make supplying it to a UITableView via a UITableViewDataSource a piece of cake. Here's a snippet on how to use the UILocalizedIndexedCollation class in conjunction with the model:</p> <pre><code> // tableData will contain an NSArray for each populated section in the table view NSMutableDictionary* tableData = [NSMutableDictionary dictionary]; NSMutableArray* myArray = [NSMutableArray array]; // Populate myArray with instances of MyModel UILocalizedIndexedCollation* indexer = [UILocalizedIndexedCollation currentCollation]; for (MyModel* data in myArray) { NSInteger index = [indexer sectionForObject:data collationStringSelector:@selector(sortableValue)]; NSNumber* key = [[NSNumber alloc] initWithInteger:index]; NSMutableArray* array = [tableData objectForKey:key]; if (array == nil) { array = [NSMutableArray new]; // Will be released after creating a sorted array in the following section [tableData setObject:array forKey:key]; } [array addObject:data]; [key release]; } [tableData enumerateKeysAndObjectsUsingBlock:^(id key, id array, BOOL* stop) { NSMutableArray* sortedArray = [[indexer sortedArrayFromArray:array collationStringSelector:@selector(sortableValue)] mutableCopy]; [tableData setObject:sortedArray forKey:key]; [array release]; }]; </code></pre> <p>One quick note about UILocalizedIndexedCollation (from Apple's documentation):</p> <blockquote> <p>If the application provides a Localizable.strings file for the current language preference, the indexed-collation object localizes each string returned by the method identified by selector.</p> </blockquote> <p>So make sure you provide a Localizable.strings for each language you want to support, or your table view will only have sections A-Z and #.</p> <p>It took me a while to work out all of the details on this, so I hope it becomes useful for other people. If you see any ways I can improve this, please let me know!</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload