排序是应用常见需求之一,如何正确优雅的实现一个排序,NSSortDescriptor或许是一个非常好的选择。

NSSortDescriptor由3个参数组成:

  • key(键):对于一个给定的集合,将对集合种的每个对象按照该键来进行排序
  • ascending(升序):指定集合按照升序(YES)还是降序(NO)进行排序
  • selector(方法子):排序时的比较函数,当对字符串进行排序时,应当加入localizedStandardCompare:选择器,它将根据语言规则进行排序(例如大小写,变音符号等等的顺序)

1.如何使用

NSSortDescriptor主要针对各种集合排序,NSArray,NSMutableArray,NSSet,NSOrderedSet,NSMutableOrderedSet

如果集合是可变的,则对集合本身排序例如

  • NSMutableOrderedSetsortUsingDescriptors:
  • NSMutableArraysortUsingDescriptors:

如果集合是可变的,则返回一个排好序的新集合例如

  • NSArraysortedArrayUsingDescriptors:
  • NSSetsortedArrayUsingDescriptors:
  • NSOrderedSetsortedArrayUsingDescriptors:

注意排序描述是一个数组,也就是排序可以支持按照多个描述综合排序。如果存在多个规则先满足前面的规则再满足后面的规则。例如两个元素按照第一天规则顺序一致,那么如果还存在第二天规则,它们将按照第二条规则继续排序,如果前面的规则已经区分出顺序后面的规则将失效。

2.实例说明

为了更好的描述,假如我们有一个Person对象,它有NSString * 类型的姓和名属性,以及一个NSNumber类型的年龄属性。

1
2
3
4
5
6
7
@interface Person : NSObject

@property (nonatomic, copy  ) NSString *firstName;
@property (nonatomic, copy  ) NSString *lastName;
@property (nonatomic, strong) NSNumber *age;

@end

给定以下数据集:

index 0 1 2 3 4
firstName Alice Bod Charlie Quentin
lastName Smith Jones Smith Alberts
age 24 27 33 31 19

使用不同的NSSortDescriptor的不同组合来将它们排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
NSArray *firstNames = @[@"Alice", @"Bod", @"Charlie", @"Quentin", @""];
NSArray *lastNames = @[@"Smith", @"Jones", @"Smith", @"", @"Alberts"];
NSArray *ages = @[@24, @27, @33, @31, @12];

NSMutableArray *people = [NSMutableArray array];
[firstNames enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    Person *person = [[Person alloc] init];
    person.firstName = [firstNames objectAtIndex:idx];
    person.lastName = [lastNames objectAtIndex:idx];
    person.age = [ages objectAtIndex:idx];

    [people addObject:person];
}];

NSSortDescriptor *firstNameSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"firstName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSSortDescriptor *lastNameSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"lastName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSSortDescriptor *ageSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO];

NSLog(@"By age: %@",[people sortedArrayUsingDescriptors:@[ageSortDescriptor]]);
/*
 2017-06-06 23:15:02.101 NSSort​Descriptor_Demo[9103:1255482] By age: (
 "Charlie Smith 33",
 "Quentin  31",
 "Bod Jones 27",
 "Alice Smith 24",
 " Alberts 12"
 )
 */

NSLog(@"By first name: %@",[people sortedArrayUsingDescriptors:@[firstNameSortDescriptor]]);
/*
 2017-06-06 23:15:02.102 NSSort​Descriptor_Demo[9103:1255482] By first name: (
 " Alberts 12",
 "Alice Smith 24",
 "Bod Jones 27",
 "Charlie Smith 33",
 "Quentin  31"
 )
*/

NSLog(@"By last name, first name: %@",[people sortedArrayUsingDescriptors:@[lastNameSortDescriptor ,firstNameSortDescriptor]]);
/*
 2017-06-06 23:15:02.102 NSSort​Descriptor_Demo[9103:1255482] By last name, first name: (
 "Quentin  31",
 " Alberts 12",
 "Bod Jones 27",
 "Alice Smith 24",
 "Charlie Smith 33"
 )
 */

3.注意事项

  • 空字符是排在普通字符之前的
  • 基本数据类型需要包装成NSNumber对象来排序
  • 字符串类型排序需要加入localizedStandardCompare:选择器

参考链接

Comments