Ordenar diferentes entidades en un NSMutableArray por fecha

I am pushing 3 different entities in a NSMutableArray, and need to compare them on the date.

But the 3 different entities have different names for the date.

I use the 3 entities: Birthday, Events, OtherEvents with the date properties: birthday, day, date.

Does anyone has any idea how to sort it like this. It has about 40 properties in it so its not a single comparison.

Gracias por adelantado

preguntado el 28 de mayo de 14 a las 14:05

Create a category on each class that unifies the 3 different dates under the sortDate ¿propiedad? -

Another very similar solution is to define a SortableByDate protocol that defines a sortDate property. Then have the different classes implement that protocol. -

Either unify the name of the date object, make a secondary object that is a copy or reference of the first, or setup a three case sort with [object isKindOfClass:] checks on every object. -

How would you sort it then Putz 1103? how can i sort an array if an object is kind of class ... you need to sort the whole array right? -

I think @DavidRönnqvist has the best ideas (a little better than the posted answers). One more: just implement a comparator on each object (polymorphism, in OO 101). If date order is the dominant sort in most cases, the comparator could even be named -- and thus override -- compare:. -

2 Respuestas

Prueba esto:

[eventsArray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {

    NSDate *date1 = nil;
    NSDate *date2 = nil;

    if ([obj1 isKindOfClass:[Birthday class]]) {
        date1 = [obj1 birthday];
    } else if ([obj1 isKindOfClass:[Events class]) {
        date1 = [obj1 day];
    } else if ([obj1 isKindOfClass:[OtherEvents class]) {
        date1 = [obj1 date];
    }

    if ([obj2 isKindOfClass:[Birthday class]]) {
        date2 = [obj2 birthday];
    } else if ([obj2 isKindOfClass:[Events class]) {
        date2 = [obj2 day];
    } else if ([obj isKindOfClass:[OtherEvents class]) {
        date2 = [obj2 date];
    }

    return [date1 compare:date2];
}];

contestado el 28 de mayo de 14 a las 14:05

Oke good one, but this is only from two objects.. How do i do this with 40? do i have to compare the first two with eachother and the third with the last two and so on...? - David Raijmakers

Todo NSMutableArray's sortUsing methods work over every object in the array. - Austin

Okay thanks i will try it soon and then i will accept yours. Thanks already for the effort - David Raijmakers

You can maintain a dictionary mapping the class to the right property.
For sorting access it with Key Value Coding.

NSDictionary *dateMapper = @{NSStringFromClass([Birthday class]): @"birthday",
                             NSStringFromClass([Event class]): @"day",
                             NSStringFromClass([OtherEvents class]): @"date"};

[eventsArray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    NSDate *date1 = [obj1 valueForKey: dateMapper[NSStringFromClass([obj1 class])]];
    NSDate *date2 = [obj2 valueForKey: dateMapper[NSStringFromClass([obj2 class])]];

    return [date1 compare:date2];
}];

I wrote a complete command line Código de muestra.

These are the model classes I use:

@interface Birthday : NSObject
@property (nonatomic, strong) NSDate *birthday;
@property (nonatomic, copy) NSString *name;
-(id)initWithName:(NSString *) name birthdayDate:(NSDate *) date;
@end

@implementation Birthday
-(id)initWithName:(NSString *) name birthdayDate:(NSDate *) date
{
    if(self = [super init]){
        _birthday = date;
        _name = name;
    };

    return self;
}

-(NSString *)description
{
    return [NSString stringWithFormat:@"Birthday:\t %@: %@", _birthday, _name];
}
@end




@interface Event : NSObject
@property (nonatomic, strong) NSDate *day;
@property (nonatomic, copy) NSString *title;
-(id)initWithTitle:(NSString *) title date:(NSDate *) date;
@end

@implementation Event
-(id)initWithTitle:(NSString *) title date:(NSDate *) date;
{
    if(self = [super init]){
        _day  = date;
        _title = title;
    };

    return self;
}

-(NSString *)description
{
    return [NSString stringWithFormat:@"Event:\t\t %@: %@", _day, _title];
}
@end




@interface OtherEvent : NSObject
@property (nonatomic, strong) NSDate *date;
@property (nonatomic, copy) NSString *title;
-(id)initWithTitle:(NSString *) title date:(NSDate *) date;
@end

@implementation OtherEvent
-(id)initWithTitle:(NSString *) title date:(NSDate *) date;
{
    if(self = [super init]){
        _date  = date;
        _title = title;
    };

    return self;
}

-(NSString *)description
{
    return [NSString stringWithFormat:@"OtherEvent: %@: %@", _date, _title];
}
@end

This code fills the array. Note that I use a rather unknown c syntax called statement expression to create the dates. I prefer them in such sample code to structure it, but you don't need to use it:

NSMutableArray *array = [@[] mutableCopy];
[array addObject:[[Birthday alloc] initWithName:@"Bibo"
                                   birthdayDate:(
                                                 {
                                                     NSDateComponents *comps = [[NSDateComponents alloc] init];
                                                     comps.year = 1969;
                                                     comps.month = 7;
                                                     comps.day = 15;
                                                     [[NSCalendar currentCalendar] dateFromComponents:comps];
                                                 })
                  ]];

[array addObject:[[Birthday alloc] initWithName:@"Jimi Hendrix"
                                   birthdayDate:(
                                                 {
                                                     NSDateComponents *comps = [[NSDateComponents alloc] init];
                                                     comps.year = 1942;
                                                     comps.month = 11;
                                                     comps.day = 27;
                                                     [[NSCalendar currentCalendar] dateFromComponents:comps];
                                                 })
                  ]];

[array addObject:[[Event alloc] initWithTitle:@"Vacation end"
                                         date:(
                                               {
                                                   NSDateComponents *comps = [[NSDateComponents alloc] init];
                                                   comps.year = 2014;
                                                   comps.month = 6;
                                                   comps.day = 21;
                                                   [[NSCalendar currentCalendar] dateFromComponents:comps];
                                               })

                  ]];

[array addObject:[[Birthday alloc] initWithName:@"Samson"
                                   birthdayDate:(
                                                 {
                                                     NSDateComponents *comps = [[NSDateComponents alloc] init];
                                                     comps.year = 1977;
                                                     comps.month = 9;
                                                     comps.day = 3;
                                                     [[NSCalendar currentCalendar] dateFromComponents:comps];
                                                 })

                  ]];

[array addObject:[[Event alloc] initWithTitle:@"Vacation begin"
                                         date:(
                                               {
                                                   NSDateComponents *comps = [[NSDateComponents alloc] init];
                                                   comps.year = 2014;
                                                   comps.month = 6;
                                                   comps.day = 1;
                                                   [[NSCalendar currentCalendar] dateFromComponents:comps];
                                               })

                  ]];

[array addObject:[[OtherEvent alloc] initWithTitle:@"Woodstock Music and Art Festival"
                                              date:(
                                                    {
                                                        NSDateComponents *comps = [[NSDateComponents alloc] init];
                                                        comps.year = 1969;
                                                        comps.month = 15;
                                                        comps.day = 8;
                                                        [[NSCalendar currentCalendar] dateFromComponents:comps];
                                                    })
                  ]];

Now I do the sorting

NSDictionary *dateMapper = @{NSStringFromClass([Birthday class]): @"birthday",
                             NSStringFromClass([Event class]): @"day",
                             NSStringFromClass([OtherEvent class]): @"date"};

[array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    NSDate *date1 = [obj1 valueForKey: dateMapper[NSStringFromClass([obj1 class])]];
    NSDate *date2 = [obj2 valueForKey: dateMapper[NSStringFromClass([obj2 class])]];

    return [date1 compare:date2];
}];

for (id obj in array) {
    NSLog(@"%@", obj);
}

Esto resulta en:

Birthday:    1942-11-26 23:00:00 +0000: Jimi Hendrix
Birthday:    1969-07-14 23:00:00 +0000: Bibo
OtherEvent:  1970-03-07 23:00:00 +0000: Woodstock Music and Art Festival
Birthday:    1977-09-02 23:00:00 +0000: Samson
Event:       2014-05-31 22:00:00 +0000: Vacation begin
Event:       2014-06-20 22:00:00 +0000: Vacation end

contestado el 28 de mayo de 14 a las 19:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.