我想做的事情似乎很简单,但我在网上找不到任何答案。我有一个对象的NSMutableArray,假设它们是Person对象。我想对NSMutableArray按Person排序。birthDate是一个NSDate。

我认为这与这个方法有关:

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(???)];

在Java中,我将使我的对象实现Comparable,或使用集合。使用内联自定义比较器排序…在Objective-C中怎么做呢?


当前回答

比较的方法

你可以为你的对象实现一个比较方法:

- (NSComparisonResult)compare:(Person *)otherObject {
    return [self.birthDate compare:otherObject.birthDate];
}

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(compare:)];

NSSortDescriptor (better)

或者通常更好:

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                           ascending:YES];
NSArray *sortedArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];

通过向数组中添加多个键,可以轻松地按多个键排序。也可以使用自定义比较器方法。看一下文档。

块(闪亮的!)

从Mac OS X 10.6和iOS 4开始,也有可能用块排序:

NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(Person *a, Person *b) {
    return [a.birthDate compare:b.birthDate];
}];

性能

一般来说,基于块的方法比使用NSSortDescriptor要快得多,因为后者依赖于KVC。NSSortDescriptor方法的主要优点是它提供了一种使用数据而不是代码来定义排序顺序的方法,这使得它很容易,例如,用户可以通过单击标题行来对NSTableView进行排序。

其他回答

你的Person对象需要实现一个方法,比如compare:它接受另一个Person对象,并根据两个对象之间的关系返回NSComparisonResult。

然后你会调用sortedArrayUsingSelector: with @selector(compare:),这应该就完成了。

还有其他方法,但据我所知,还没有类似可比性接口的cocoa。使用sortedArrayUsingSelector:可能是最简单的方法。

在我的例子中,我使用“sortedArrayUsingComparator”对数组进行排序。请看下面的代码。

contactArray = [[NSArray arrayWithArray:[contactSet allObjects]] sortedArrayUsingComparator:^NSComparisonResult(ContactListData *obj1, ContactListData *obj2) {
    NSString *obj1Str = [NSString stringWithFormat:@"%@ %@",obj1.contactName,obj1.contactSurname];
    NSString *obj2Str = [NSString stringWithFormat:@"%@ %@",obj2.contactName,obj2.contactSurname];
    return [obj1Str compare:obj2Str];
}];

我的目标是,

@interface ContactListData : JsonData
@property(nonatomic,strong) NSString * contactName;
@property(nonatomic,strong) NSString * contactSurname;
@property(nonatomic,strong) NSString * contactPhoneNumber;
@property(nonatomic) BOOL isSelected;
@end

像这样使用嵌套对象,

NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"lastRoute.to.lastname" ascending:YES selector:@selector(caseInsensitiveCompare:)];
NSMutableArray *sortedPackages = [[NSMutableArray alloc]initWithArray:[packages sortedArrayUsingDescriptors:@[sortDescriptor]]];

lastRoute是一个对象,该对象保存着to对象,to对象保存着lastname字符串值。

我什么都试过了,但这个对我有用。在一个类中,我有另一个名为“crimeScene”的类,并希望通过“crimeScene”的属性进行排序。

这就像一个魅力:

NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"crimeScene.distance" ascending:YES];
[self.arrAnnotations sortUsingDescriptors:[NSArray arrayWithObject:sorter]];

我已经创建了一个小型的类别方法库,称为Linq to ObjectiveC,这使得这类事情更加容易。使用带有键选择器的sort方法,您可以按birthDate进行排序,如下所示:

NSArray* sortedByBirthDate = [input sort:^id(id person) {
    return [person birthDate];
}]