Sort NSArray of NSStrings like Addressbook on ipho

2020-02-26 08:46发布

I have an array of strings (names)

and i would like to sort them like how the address book on the iphone sorts them

  • eg: éli -> under E
  • eg: àli -> under A
  • eg: 4li -> under #

any suggestions?

2条回答
手持菜刀,她持情操
2楼-- · 2020-02-26 08:58

all lies within the compare: method you will use as the selector of your sorting method and more importantly with the NSDiacriticInsensitiveSearch option.

[[yourArray] sortedArrayUsingSelector:@selector(compareTheAddressBookWay:)];

Now you need to add the compareTheAddressBookWay: method in a category

@implementation NSString (YourCategory)

- (NSComparisonResult) compareTheAddressBookWay:(NSString*)iString
{
    return [self compare:iString 
                 options:NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch 
                   range:NSRangeFromString(self)
}

@end

!!Important!!:

Using sortedArrayUsingSelector: will be compliant for iOS up to 2.0
while usingsortedArrayUsingComparator: will ONLY work for iOS 4 and above.

查看更多
乱世女痞
3楼-- · 2020-02-26 09:14

You need to perform a diacritic insensitive comparison against the strings. NSString has a compare:options: method with an option of NSDiacriticInsensitiveSearch.

NSArray *array = [NSArray arrayWithObjects:@"éli", @"bob", @"earl", @"allen", @"àli", @"aaron", nil];

NSArray *sorted = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    return [(NSString*)obj1 compare:obj2 options:NSDiacriticInsensitiveSearch|NSCaseInsensitiveSearch];
}];

Edit:

Here is a full example that will section the results based on the first character diacritic insensitive. I put in a dictionary so you would need to keep track of the sorted keys on your own to display properly.

NSArray *array = [NSArray arrayWithObjects:@"éli", @"bob", @"earl", @"allen", @"àli", nil];

NSArray *sorted = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    return [(NSString*)obj1 compare:obj2 options:NSDiacriticInsensitiveSearch|NSCaseInsensitiveSearch];
}];

NSMutableDictionary *sectioned = [NSMutableDictionary dictionary];
NSString *firstChar = nil;

for(NSString *str in sorted)
{
    //Ignore empty strings
    if(![str length])continue;

    NSMutableArray *names = nil;

    //Compare the first character using diacritic insensitive search
    if([str compare:firstChar options:NSDiacriticInsensitiveSearch|NSCaseInsensitiveSearch range:NSMakeRange(0, 1)] == NSOrderedSame)
    {
        names = [sectioned objectForKey:firstChar];
    }
    else
    {
        //decomposedStringWithCanonicalMapping is where the magic happens
        //(it removes the accent mark)
        firstChar = [[str decomposedStringWithCanonicalMapping] substringToIndex:1];
        names = [NSMutableArray array];
        [sectioned setObject:names forKey:firstChar];
    }

    [names addObject:str];
}

NSLog(@"sorted: %@", sorted);
//This is sectioned like the address app
NSLog(@"sectioned: %@", sectioned);
查看更多
登录 后发表回答