Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort NSmutableArray that contains 2 types of object?

I have an NSMutableArray that contains 2 types of Objects.

Both objects contain a field for dates (date Strings with different formats) with different names.

What's the best and fastest way to sort them all based on the date? Is it possible to use an NSSortDescriptor in this situation?

like image 332
aryaxt Avatar asked Aug 17 '11 22:08

aryaxt


People also ask

How do you sort an array of objects in Objective C?

The trick to sorting an array is a method on the array itself called "sortedArrayUsingDescriptors:". The method takes an array of NSSortDescriptor objects. These descriptors allow you to describe how your data should be sorted. So that handles the simple case, but what about if you want to sort your custom objects.

What is difference between NSArray and NSMutableArray?

The primary difference between NSArray and NSMutableArray is that a mutable array can be changed/modified after it has been allocated and initialized, whereas an immutable array, NSArray , cannot.

How do you sort an array of strings in Objective C?

For just sorting array of strings: sorted = [array sortedArrayUsingSelector:@selector(compare:)]; For sorting objects with key "name": NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(compare:)]; sorted = [array sortedArrayUsingDescriptors:@[sort]];

What is NSMutableArray?

The NSMutableArray class declares the programmatic interface to objects that manage a modifiable array of objects. This class adds insertion and deletion operations to the basic array-handling behavior inherited from NSArray . NSMutableArray is “toll-free bridged” with its Core Foundation counterpart, CFMutableArray .


2 Answers

If you are targeting Mac OS X v10.6 or iOS4 and higher you can sort using comparator similar to this

NSDateFormatter *formatter1 = ...; //create and configure date formatter for Class1
NSDateFormatter *formatter2 = ...; //create and configure date formatter for Class2


[arrayOfObjects sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    NSDate *date1 = nil, *date2 = nil;
    //Get first objects date
    if([obj1 isKindOfClass:[Class1 class]])
    {
        date1 = [formatter1 dateFromString:[obj1 class1Date]];
    }
    else if([obj1 isKindOfClass:[Class2 class]])
    {
        date1 = [formatter2 dateFromString:[obj1 class2Date]];
    }

    //Get second objects date
    if([obj2 isKindOfClass:[Class1 class]])
    {
        date2 = [formatter1 dateFromString:[obj2 class1Date]];
    }
    else if([obj2 isKindOfClass:[Class2 class]])
    {
        date2 = [formatter2 dateFromString:[obj2 class2Date]];
    }

    NSAssert(date1 != nil, @"Could not parse date from %@", obj1);
    NSAssert(date2 != nil, @"Could not parse date from %@", obj2);

    return [date1 compare:date2];
}];

Besides checking for the class you could also check if it responds to selector.

like image 120
Joe Avatar answered Oct 11 '22 17:10

Joe


You could add a category to unify the date field name. Let's say class A's instances have a field "dateString" and class B's instances have a field "creationDateString"... You could do this:

@implementation A (SortByDate)

-(NSDate*)sortDate
{
    static NSDateFormatter * formatter = nil ;
    static dispatch_once_t once = 0 ;
    dispatch_once( & once, ^{ formatter = ... } ) ;

    return [ formatter dateFromString:self.dateString ] ;
}
@end

@implementation B (SortByDate)
-(NSDate*)sortDate
{
    static NSDateFormatter * formatter = nil ;
    static dispatch_once_t once = 0 ;
    dispatch_once( & once, ^{ formatter = ... } ) ;

    return [ formatter dateFromString:self.creationDateString ] ;
}
@end

Now you can sort all objects in your array by their sortDate property:

NSArray * sortedByDateArray = [ unsortedArray sortedArrayUsingComparator:^( id a, id b ){
    return [ [ a sortDate ] compare:[ b sortDate ] ] ;
}];

EDIT Or with a sort descriptor:

NSArray * sortedArray = [ unsortedArray sortedArrayUsingDescriptors:[ NSArray arrayWithObject:[ NSSortDescriptor sortDescriptorWithKey:@"sortDate" ascending:YES ] ] ] ;
like image 24
nielsbot Avatar answered Oct 11 '22 15:10

nielsbot