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

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

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

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


当前回答

使用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/

其他回答

我只是根据自定义需求做了多级排序。

//对值排序

    [arrItem sortUsingComparator:^NSComparisonResult (id a, id b){

    ItemDetail * itemA = (ItemDetail*)a;
    ItemDetail* itemB =(ItemDetail*)b;

    //item price are same
    if (itemA.m_price.m_selling== itemB.m_price.m_selling) {

        NSComparisonResult result=  [itemA.m_itemName compare:itemB.m_itemName];

        //if item names are same, then monogramminginfo has to come before the non monograme item
        if (result==NSOrderedSame) {

            if (itemA.m_monogrammingInfo) {
                return NSOrderedAscending;
            }else{
                return NSOrderedDescending;
            }
        }
        return result;
    }

    //asscending order
    return itemA.m_price.m_selling > itemB.m_price.m_selling;
}];

https://sites.google.com/site/greateindiaclub/mobil-apps/ios/multilevelsortinginiosobjectivec

比较的方法

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

- (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进行排序。

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

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

像这样使用嵌套对象,

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

从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];

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