How do I sort an NSMutableArray with custom object

2018-12-30 23:43发布

What I want to do seems pretty simple, but I can't find any answers on the web. I have an NSMutableArray of objects, and let's say they are 'Person' objects. I want to sort the NSMutableArray by Person.birthDate which is an NSDate.

I think it has something to do with this method:

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

In Java I would make my object implement Comparable, or use Collections.sort with an inline custom comparator...how on earth do you do this in Objective-C?

25条回答
后来的你喜欢了谁
2楼-- · 2018-12-31 00:32

If you're just sorting an array of NSNumbers, you can sort them with 1 call:

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

That works because the objects in the array (NSNumber objects) implement the compare method. You could do the same thing for NSString objects, or even for an array of custom data objects that implement a compare method.

Here's some example code using comparator blocks. It sorts an array of dictionaries where each dictionary includes a number in a key "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;
 }];

The code above goes through the work of getting an integer value for each sort key and comparing them, as an illustration of how to do it. Since NSNumber objects implement a compare method, it could be rewritten much more simply:

 #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];
 }];

or the body of the comparator could even be distilled down to 1 line:

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

I tend to prefer simple statements and lots of temporary variables because the code is easier to read, and easier to debug. The compiler optimizes away the temporary variables anyway, so there is no advantage to the all-in-one-line version.

查看更多
长期被迫恋爱
3楼-- · 2018-12-31 00:32

Sort using NSComparator

If we want to sort custom objects we need to provide NSComparator, which is used to compare custom objects. The block returns an NSComparisonResult value to denote the ordering of the two objects. So in order to sort whole array NSComparator is used in following way.

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

Sorts Using NSSortDescriptor
Let’s assume, as an example, that we have an array containing instances of a custom class, Employee has attributes firstname, lastname and age. The following example illustrates how to create an NSSortDescriptor that can be used to sort the array contents in ascending order by the age key.

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

Sort using Custom Comparisons
Names are strings, and when you sort strings to present to the user you should always use a localized comparison. Often you also want to perform a case insensitive comparison. Here comes an example with (localizedStandardCompare:) to order the array by last and first name.

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

For reference and detailed discussion please refer: 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/

查看更多
永恒的永恒
4楼-- · 2018-12-31 00:32

In my case, I use "sortedArrayUsingComparator" to sort an array. Look at the below code.

contactArray = [[NSArray arrayWithArray:[contactSet allObjects]] sortedArrayUsingComparator:^NSComparisonResult(ContactListData *obj1, ContactListData *obj2) {
    NSString *obj1Str = [NSString stringWithFormat:@"%@ %@",obj1.contactName,obj1.contactSurname];
    NSString *obj2Str = [NSString stringWithFormat:@"%@ %@",obj2.contactName,obj2.contactSurname];
    return [obj1Str compare:obj2Str];
}];

Also my object is,

@interface ContactListData : JsonData
@property(nonatomic,strong) NSString * contactName;
@property(nonatomic,strong) NSString * contactSurname;
@property(nonatomic,strong) NSString * contactPhoneNumber;
@property(nonatomic) BOOL isSelected;
@end
查看更多
骚的不知所云
5楼-- · 2018-12-31 00:35

iOS 4 blocks will save you :)

featuresArray = [[unsortedFeaturesArray sortedArrayUsingComparator: ^(id a, id b)  
{
    DMSeatFeature *first = ( DMSeatFeature* ) a;
    DMSeatFeature *second = ( DMSeatFeature* ) b;

    if ( first.quality == second.quality )
        return NSOrderedSame;
    else
    {
        if ( eSeatQualityGreen  == m_seatQuality || eSeatQualityYellowGreen == m_seatQuality || eSeatQualityDefault  == m_seatQuality )
        {
            if ( first.quality < second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        }
        else // eSeatQualityRed || eSeatQualityYellow
        {
            if ( first.quality > second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        } 
    }
}] retain];

http://sokol8.blogspot.com/2011/04/sorting-nsarray-with-blocks.html a bit of description

查看更多
残风、尘缘若梦
6楼-- · 2018-12-31 00:35

I just done multi level sorting based on custom requirement.

//sort the values

    [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

查看更多
情到深处是孤独
7楼-- · 2018-12-31 00:39

Sorting NSMutableArray is very simple:

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];
查看更多
登录 后发表回答