Сортиране на NSmutableArray, който съдържа 2 типа обект?

Имам NSMutableArray, който съдържа 2 типа обекти.

И двата обекта съдържат поле за дати (низове с дата с различни формати) с различни имена.

Кой е най-добрият и бърз начин да ги сортирате всички въз основа на датата? Възможно ли е да се използва NSSortDescriptor в тази ситуация?


person aryaxt    schedule 17.08.2011    source източник


Отговори (2)


Ако сте насочени към Mac OS X v10.6 или iOS4 и по-нови, можете да сортирате с помощта на сравнение, подобно на това

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

Освен проверка за класа, можете също да проверите дали отговаря на селектор.

person Joe    schedule 17.08.2011
comment
Прехвърлянето на обектите от id е съвсем ненужно. - person Chuck; 18.08.2011
comment
Да, има няколко sortUsing... метода на NSArray и всеки един от тях трябва да свърши работа. - person Hot Licks; 18.08.2011
comment
Между другото - няма нужда да изпълнявате isKindOfClass: или respondsToSelector:, ако използвате категории.. - person nielsbot; 29.08.2012

Можете да добавите категория, за да обедините името на полето за дата. Да кажем, че екземплярите на клас A имат поле "dateString", а екземплярите на клас B имат поле "creationDateString"... Можете да направите това:

@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

Сега можете да сортирате всички обекти във вашия масив по тяхното свойство sortDate:

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

РЕДАКТИРАНЕ Или с дескриптор за сортиране:

NSArray * sortedArray = [ unsortedArray sortedArrayUsingDescriptors:[ NSArray arrayWithObject:[ NSSortDescriptor sortDescriptorWithKey:@"sortDate" ascending:YES ] ] ] ;
person nielsbot    schedule 28.08.2012
comment
можете дори да създадете хранилище за всеки екземпляр за вашето ново свойство sortDate, така че то трябва да бъде преизчислено само с основните промени в низа. - person nielsbot; 29.08.2012