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

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

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

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


当前回答

从iOS 4开始,你也可以使用块来排序。

对于这个特殊的例子,我假设数组中的对象有一个'position'方法,它返回一个NSInteger。

NSArray *arrayToSort = where ever you get the array from... ;
NSComparisonResult (^sortBlock)(id, id) = ^(id obj1, id obj2) 
{
    if ([obj1 position] > [obj2 position]) 
    { 
        return (NSComparisonResult)NSOrderedDescending;
    }
    if ([obj1 position] < [obj2 position]) 
    {
        return (NSComparisonResult)NSOrderedAscending;
    }
    return (NSComparisonResult)NSOrderedSame;
};
NSArray *sorted = [arrayToSort sortedArrayUsingComparator:sortBlock];

注意:排序后的数组将被自动释放。

其他回答

像这样使用嵌套对象,

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字符串值。

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

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

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

使用NSComparator进行排序

如果我们想对自定义对象进行排序,我们需要提供NSComparator,它用于比较自定义对象。该块返回一个NSComparisonResult值来表示两个对象的排序。为了对整个数组进行排序,NSComparator的用法如下。

NSArray *sortedArray = [employeesArray sortedArrayUsingComparator:^NSComparisonResult(Employee *e1, Employee *e2){
    return [e1.firstname compare:e2.firstname];    
}];

使用NSSortDescriptor进行排序 让我们假设,作为一个例子,我们有一个包含自定义类实例的数组,Employee具有属性firstname, lastname和age。下面的例子说明了如何创建一个NSSortDescriptor,该NSSortDescriptor可用于按年龄键升序对数组内容进行排序。

NSSortDescriptor *ageDescriptor = [[NSSortDescriptor alloc] initWithKey:@"age" ascending:YES];
NSArray *sortDescriptors = @[ageDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

使用自定义比较进行排序 名称是字符串,当您对字符串进行排序以呈现给用户时,您应该始终使用本地化比较。通常您还希望执行不区分大小写的比较。下面是一个示例,使用(localizedStandardCompare:)按姓氏和名字对数组进行排序。

NSSortDescriptor *lastNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"lastName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSSortDescriptor * firstNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"firstName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSArray *sortDescriptors = @[lastNameDescriptor, firstNameDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

如需参考及详细讨论,请参考: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/SortDescriptors/Articles/Creating.html http://www.ios-blog.co.uk/tutorials/objective-c/how-to-sort-nsarray-with-custom-objects/

你必须创建sortDescriptor,然后你可以像下面这样使用sortDescriptor对nsmutablearray进行排序。

 let sortDescriptor = NSSortDescriptor(key: "birthDate", ascending: true, selector: #selector(NSString.compare(_:)))
 let array = NSMutableArray(array: self.aryExist.sortedArray(using: [sortDescriptor]))
 print(array)

如果你只是排序一个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]];

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