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

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

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

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


当前回答

在Georg Schölly的第二个答案中有一个缺失的步骤,但它可以正常工作。

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

//添加's',因为我复制和粘贴时浪费了时间,在sortedArrayUsingDescriptors中没有's'就失败了

其他回答

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

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

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

对于NSMutableArray,使用sortUsingSelector方法。它对位置进行排序,而不创建新实例。

如果你只是排序一个nsnumber数组,你可以用一个调用来排序它们:

[arrayToSort sortUsingSelector: @selector(compare:)];

这是因为数组中的对象(NSNumber对象)实现了比较方法。你可以为NSString对象做同样的事情,甚至为实现了比较方法的自定义数据对象数组做同样的事情。

下面是一些使用比较器块的示例代码。它对字典数组进行排序,其中每个字典在键“sort_key”中包含一个数字。

#define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
 ^(id obj1, id obj2) 
  {
  NSInteger value1 = [[obj1 objectForKey: SORT_KEY] intValue];
  NSInteger value2 = [[obj2 objectForKey: SORT_KEY] intValue];
  if (value1 > value2) 
{
  return (NSComparisonResult)NSOrderedDescending;
  }

  if (value1 < value2) 
{
  return (NSComparisonResult)NSOrderedAscending;
  }
    return (NSComparisonResult)NSOrderedSame;
 }];

上面的代码演示了如何为每个排序键获取整数值并对它们进行比较。因为NSNumber对象实现了一个比较方法,它可以重写得更简单:

 #define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
^(id obj1, id obj2) 
 {
  NSNumber* key1 = [obj1 objectForKey: SORT_KEY];
  NSNumber* key2 = [obj2 objectForKey: SORT_KEY];
  return [key1 compare: key2];
 }];

或者比较器的主体甚至可以被提炼为一行:

  return [[obj1 objectForKey: SORT_KEY] compare: [obj2 objectForKey: SORT_KEY]];

我倾向于使用简单的语句和大量的临时变量,因为代码更容易阅读,也更容易调试。编译器无论如何都会优化掉临时变量,因此,全在一行中的版本没有任何优势。

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

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

排序NSMutableArray非常简单:

NSMutableArray *arrayToFilter =
     [[NSMutableArray arrayWithObjects:@"Photoshop",
                                       @"Flex",
                                       @"AIR",
                                       @"Flash",
                                       @"Acrobat", nil] autorelease];

NSMutableArray *productsToRemove = [[NSMutableArray array] autorelease];

for (NSString *products in arrayToFilter) {
    if (fliterText &&
        [products rangeOfString:fliterText
                        options:NSLiteralSearch|NSCaseInsensitiveSearch].length == 0)

        [productsToRemove addObject:products];
}
[arrayToFilter removeObjectsInArray:productsToRemove];