http://blog.ablepear.com/2011/12/objective-c-tuesdays-more-nsarray.html
上次我们讲了C数组和NSArray排序,今天我们继续讲讲使用NSSortDescriptors为NSArray排序.
NSArray要求指定比较函数来完成排序.当为一些简单类型(NSString, NSDate)NSArray排序的时候,比较函数十分容易编写,并且一些普通对象都有比较函数,像-caseInsensitiveCompare: 和 -localizedCompare:.
当为复杂类型NSArray排序的时候,编写比较函数就更麻烦并且更易出错.这是Person类的接口:
// Person.h
@interface Person : NSObject
@property (strong) Address *address;
@property (strong) NSDate *birthdate;
@property (copy) NSString *firstName;
@property (copy) NSString *lastName;
@end
这是Person要使用的Address类的接口:
// Address.h
@interface Address : NSObject
@property (copy, nonatomic) NSString *street;
@property (copy, nonatomic) NSString *city;
@property (copy, nonatomic) NSString *state;
@property (copy, nonatomic) NSString *country;
@property (copy, nonatomic) NSString *postalCode;
@end
我们有一个Person的NSArray,我们要按country,lastName,firstName来给它排序.这是用比较block的一种实现方式:
// sort Person objects by lastName, firstName
Person *frodo = [Person new];
[frodo setFirstName:@"Frodo"];
[frodo setLastName:@"Baggins"];
// ...
[[frodo address] setCountry:@"Shire"];
Person *bilbo = [Person new];
[bilbo setFirstName:@"Bilbo"];
[bilbo setLastName:@"Baggins"];
// ...
[[bilbo address] setCountry:@"Shire"];
Person *legolas = [Person new];
[legolas setFirstName:@"Legolas"];
[legolas setLastName:@"Greenleaf"];
// ...
[[legolas address] setCountry:@"Mirkwood"];
NSArray *people = [NSArray arrayWithObjects:frodo, bilbo, legolas, nil];
NSArray *sortedPeople = [people sortedArrayUsingComparator:^(id item1, id item2) {
Person *person1 = item1;
Person *person2 = item2;
// NSComparisonResult is a typedef for int
NSComparisonResult result = [[[person1 address] country] compare:[[person2 address] lastName]];
if (result) {
return result;
}
result = [[person1 lastName] compare:[person2 lastName]];
if (result) {
return result;
}
result = [[person1 firstName] compare:[person2 firstName]];
if (result) {
return result;
}
return NSOrderedSame; // NSOrderedSame == 0
}];
// sortedPeople contains:
// Legolas Greenleaf (Mirkwood)
// Bilbo Baggins (Shire)
// Frodo Baggins (Shire)
多字段比较的通用模式是简单的,依次检查每个字段,如果比较结果不是0,停止并返回比较结果;如果所有字段都相等,返回0(或者用更具描述性的NSOrderedSame).如果你需要深入子孙对象去检查字段,这会变得非常繁琐.
幸运的是有简单的方法解决这个问题.NSArray有一个叫-sortedArrayUsingDescriptors:的方法,它接收一组NSSortDescriptor 对象作为参数.每个NSSortDescriptor 对象指定一个key路径和排序方向(升序或者降序)。数组中NSSortDescriptors的顺序决定每个字段的优先级.如果你不熟悉KVC(Key Value Coding),你可能没有遇到过key路径.KVC允许你用字符型的字段名称来get,set对象字段.访问子孙对象的字段,你需要使用.分隔的key组成的key路径.KVC有很多有意思的东西,但今天我们只涉及构建一组NSSortDescriptors:
NSSortDescriptor *byCountry = [NSSortDescriptor sortDescriptorWithKey:@"address.country"
ascending:YES];
NSSortDescriptor *byLastName = [NSSortDescriptor sortDescriptorWithKey:@"lastName"
ascending:YES];
NSSortDescriptor *byFirstName = [NSSortDescriptor sortDescriptorWithKey:@"firstName"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:byCountry, byLastName, byFirstName, nil];
注意byCountry 排序描述符用key路径@"address.country":,它首先取得Person对象的address属性值,然后取得address的country属性值.Key路径可以任意深.
使用排序描述符组是简单的:
NSArray *sortedPeople = [people sortedArrayUsingDescriptors:sortDescriptors];
// sortedPeople contains:
// Legolas Greenleaf (Mirkwood)
// Bilbo Baggins (Shire)
// Frodo Baggins (Shire)
这使用创建复杂的排序规则变得容易,并且你不再受限于字段的缺省比较函数.你可以为一个比较函数指定一个selector:
// specify a method to call on the lastName object
NSSortDescriptor *byLastName = [NSSortDescriptor sortDescriptorWithKey:@"lastName"
ascending:YES
selector:@selector(caseInsensitiveCompare:)];
或者为了更专门的比较,你可以传递NSComparator的block:
// sort descriptor using length of last name
NSSortDescriptor *byLastNameLength = [NSSortDescriptor sortDescriptorWithKey:@"lastName"
ascending:YES
comparator:^(id item1, id item2) {
NSString *lastName1 = item1;
NSString *lastName2 = item2;
// cast result to NSComparisonResult so that the
// compiler infers the correct return type
return (NSComparisonResult) ([lastName1 length] - [lastName2 length]);
}];
用NSSortDescriptors 指定复杂排序规则是比较易读易写易维护的声明代码,并且大多数情况你你都应该考虑使用NSSortDescriptor,而不是自己编写比较函数.
分享到:
相关推荐
这些代码示例通常会包括创建一个未排序的数组,然后使用上述方法之一对其进行排序,并显示排序后的结果,以便更好地理解和学习`NSArray`的排序机制。 总之,`NSArray`的排序可以通过多种方式实现,包括`...
1. NSArray排序:由于NSArray本身不支持排序,如果需要对NSArray进行排序,通常会先将其转换为可变数组NSMutableArray,进行排序后再转回NSArray。 2. NSMutableArray排序:提供了`sortUsingComparator:`和`...
在这种情况下,可以在比较器中添加更多的判断: ```swift let sortedPeople = people.sorted { (p1, p2) in if p1.age == p2.age { return p1.name 当年龄相同时,按名字排序 } else { return p1.age 首先按...
冒泡排序是另一种简单的排序算法,它重复地遍历待排序的序列,比较每对相邻元素,然后交换位置,直到没有更多的交换,即序列已排序。Objective-C的实现如下: ```objc - (void)bubbleSort:(NSMutableArray *)array ...
在iOS开发中,经常需要对汉字或英文名称的数组进行排序和分组,以便于用户更方便地查找和浏览。这个任务通常涉及到Objective-C(OC)编程语言的使用,因此我们今天将深入探讨如何在iOS应用中实现这个功能。 首先,...
这需要额外的数据结构来管理不同类别,同时在拖动时,图标不仅可以改变位置,还可以改变所属的分类,这需要更复杂的数据操作和界面更新逻辑。 总的来说,这个项目涵盖了iOS开发中的手势识别、数据模型同步、自定义...
如果这是一个示例项目,通过查看和学习源代码,我们可以更深入地理解如何在实践中解决汉字排序问题。 总的来说,“ios-汉字排序.zip”提供的资源对于了解和实践iOS中的汉字排序是一个宝贵的工具。通过学习和应用...
而这个开源库提供了一个解决方案,它可能包含一个或多个类,如`Pinyin`类,包含`convertToPinyin`这样的方法,用于将汉字转换为拼音,然后可以根据拼音的首字母进行排序。 在给出的压缩包文件名`pinyin.h`和`pinyin...
当需要根据多个属性进行排序时,可以使用`sortUsingDescriptors:`方法,它接受一个NSArray对象,其中包含NSSortDescriptor对象,每个描述符代表一种排序方式。例如: ```objc NSMutableArray *descriptors = @[ ...
然后,我们将`sortDescriptor`添加到一个`NSArray`中,这样我们可以传递多个排序规则: ```objc NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; ``` 最后,使用`...
1. 扩展系统类的功能,如上述的NSArray排序方法。 2. 给私有分类添加辅助方法,以提高代码组织的清晰度。 3. 在没有权限修改源码的第三方库中添加功能或修复问题。 4. 实现一些常用的工具方法,如字符串转日期、颜色...
排序方法的选择取决于你的需求:如果你不想改变原数组,或者需要根据多个属性进行复杂排序,那么`NSArray`的`sortedArrayUsingDescriptors:`更适合;如果你需要就地排序,并且数组可以被修改,`NSMutableArray`的`...
"LHQListSort.zip"文件可能包含了如何在iOS应用中实现自定义排序功能,特别是针对包含多音字情况的特殊处理。以下是对这一主题的详细讲解: 首先,数据排序在iOS中通常是基于数组的。假设我们有一个包含模型对象的...
在iOS开发中,实现联系人按照首字母进行排序是一个常见的需求,这有助于用户更方便地查找和管理他们的联系人列表。`UILocalizedIndexedCollation`是苹果提供的一种内置的排序机制,它允许开发者轻松地根据字符的首...
这个“IOS应用源码之Array.rar”文件很可能包含了一个或多个示例项目,用于演示如何在iOS应用中使用NSArray及其相关的类,如NSMutableArray。 NSArray是一个不可变的集合,意味着一旦创建,就不能更改其内容。它...
- **数据展示**:在列表或表格视图中,显示数据时,可以先对数据进行拼音排序,提供更好的用户体验。 - **搜索优化**:在搜索功能中,预处理数据并按拼音排序,可以提高搜索速度。 5. **注意事项** - **多音字...
在获取到联系人的名字拼音后,可以利用NSArray的sortedArrayUsingComparator方法进行排序,根据拼音首字母进行升序排列。 在UITableViewCell中展示数据时,我们可以创建一个自定义的UITableViewCell子类,用于显示...
在实际开发中,可能还需要处理更复杂的情况,例如考虑排序规则(如拼音排序)、处理缺失数据等。同时,为了提高性能,可以考虑使用`NSOrderedSet`代替`NSArray`,或者在现代版本的iOS中使用`Swift`,利用其更强大的...
在Objective-C(简称OC)中,数组是一种常用的数据结构,用于存储多个有序的元素。当你需要将数组中的元素顺序反转,即实现数组的倒序,可以采用多种方法。本篇文章将详细讲解如何在OC中实现数组倒序的操作。 首先...
//取第一页,每页10条按条件查询数据,指定字段,设置分页,设置排序,返回结果为NSArray 排序中 desc 代表 降序,asc代表升序 单个字段排序 如 id desc 多个字段排序 如 id,wheel ascNSString *where = @"name='...