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

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

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

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


当前回答

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

这就像一个魅力:

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

其他回答

使用NSSortDescriptor对自定义对象的NSMutableArray进行排序

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

比较的方法

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

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

-(NSMutableArray*) sortArray:(NSMutableArray *)toBeSorted 
{
  NSArray *sortedArray;
  sortedArray = [toBeSorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b) 
  {
    return [a compare:b];
 }];
 return [sortedArray mutableCopy];
}

Swift中的数组排序


对于Swifty Person来说,下面是一个非常干净的技术,可以在全球范围内实现上述目标。让我们有一个User类的例子,它有一些属性。

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
}

现在我们有了一个数组,我们需要在createdDate的基础上升序和/或降序排序。因此,让我们添加一个日期比较函数。

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
    func checkForOrder(_ otherUser: User, _ order: ComparisonResult) -> Bool {
        if let myCreatedDate = self.createdDate, let othersCreatedDate = otherUser.createdDate {
            //This line will compare both date with the order that has been passed.
            return myCreatedDate.compare(othersCreatedDate) == order
        }
        return false
    }
}

现在让我们有一个扩展数组为用户。简单地说,让我们为那些只有User对象的数组添加一些方法。

extension Array where Element: User {
    //This method only takes an order type. i.e ComparisonResult.orderedAscending
    func sortUserByDate(_ order: ComparisonResult) -> [User] {
        let sortedArray = self.sorted { (user1, user2) -> Bool in
            return user1.checkForOrder(user2, order)
        }
        return sortedArray
    }
}

升序使用

let sortedArray = someArray.sortUserByDate(.orderedAscending)

降序使用

let sortedArray = someArray.sortUserByDate(.orderedAscending)

同一订单的使用

let sortedArray = someArray.sortUserByDate(.orderedSame)

只有当数组为类型时,上述扩展方法才可访问 [User] || Array<用户> .使用实例

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

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