我想做的事情似乎很简单,但我在网上找不到任何答案。我有一个NSMutableArray
对象,让我们说它们是'Person' 对象。我想通过 Person.birthDate 对NSMutableArray
进行排序,这是一个NSDate
。
我认为这与这个方法有关:
NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(???)];
在 Java 中,我会使我的对象实现 Comparable,或者使用带有内联自定义比较器的 Collections.sort ... 你到底如何在 Objective-C 中执行此操作?
要么为对象实现 compare 方法:
- (NSComparisonResult)compare:(Person *)otherObject {
return [self.birthDate compare:otherObject.birthDate];
}
NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(compare:)];
或者通常更好:
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(id a, id b) {
NSDate *first = [(Person*)a birthDate];
NSDate *second = [(Person*)b birthDate];
return [first compare:second];
}];
通常, -compare:
和基于块的方法比使用NSSortDescriptor
要快得多,因为后者依赖于 KVC。 NSSortDescriptor
方法的主要优点是它提供了一种使用数据而不是代码定义排序顺序的方法,这使得设置变得容易,因此用户可以通过单击标题行对NSTableView
进行排序。
请参阅NSMutableArray
方法sortUsingFunction:context:
您需要设置一个比较函数,它接受两个对象(类型为Person
,因为您要比较两个Person
对象)和一个上下文参数。
这两个对象只是Person
实例。第三个对象是一个字符串,例如 @“birthDate”。
该函数返回一个NSComparisonResult
:它返回NSOrderedAscending
如果PersonA.birthDate
< PersonB.birthDate
。它将返回NSOrderedDescending
如果PersonA.birthDate
> PersonB.birthDate
。最后,它会返回NSOrderedSame
如果PersonA.birthDate
== PersonB.birthDate
。
这是粗糙的伪代码; 你需要充实一个日期对于另一个日期 “更少”,“更多” 或 “相等” 意味着什么(例如比较秒 - 自 - 纪元等):
NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
if ([firstPerson birthDate] < [secondPerson birthDate])
return NSOrderedAscending;
else if ([firstPerson birthDate] > [secondPerson birthDate])
return NSOrderedDescending;
else
return NSOrderedSame;
}
如果你想要更紧凑的东西,你可以使用三元运算符:
NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
return ([firstPerson birthDate] < [secondPerson birthDate]) ? NSOrderedAscending : ([firstPerson birthDate] > [secondPerson birthDate]) ? NSOrderedDescending : NSOrderedSame;
}
如果你这么做的话,内联也许可以加快一点。
我在 iOS 4 中使用块来完成此操作。不得不将我的数组元素从 id 转换为我的类类型。在这种情况下,它是一个名为 Score 的类,其中包含一个名为 points 的属性。
如果数组的元素不是正确的类型,你还需要决定该怎么做,对于这个例子我刚刚返回NSOrderedSame
,但是在我的代码中我虽然是异常。
NSArray *sorted = [_scores sortedArrayUsingComparator:^(id obj1, id obj2){
if ([obj1 isKindOfClass:[Score class]] && [obj2 isKindOfClass:[Score class]]) {
Score *s1 = obj1;
Score *s2 = obj2;
if (s1.points > s2.points) {
return (NSComparisonResult)NSOrderedAscending;
} else if (s1.points < s2.points) {
return (NSComparisonResult)NSOrderedDescending;
}
}
// TODO: default is the same?
return (NSComparisonResult)NSOrderedSame;
}];
return sorted;
PS:这是按降序排序。