2011-05-21 22 views
13

Estoy intentando ordenar un NSArray que se llena con objetos personalizados. Cada objeto tiene una propiedad startDateTime que es del tipo NSDate.Ordenar NSArray de objetos personalizados por sus propiedades NSDate

El siguiente código da como resultado una matriz, sortedEventArray, pero no está ordenada. ¿Voy por esto de una manera completamente equivocada o me estoy perdiendo algo pequeño?

NSSortDescriptor *dateDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"startDateTime" 
                   ascending:YES]; 
NSArray *sortDescriptors = [NSArray arrayWithObject:dateDescriptor]; 
NSArray *sortedEventArray = [nodeEventArray sortedArrayUsingDescriptors:sortDescriptors]; 
+0

código parece perfectamente bien. ¿Estás seguro de que tienes la clave correcta? –

+0

@Firoze: Sí, he comprobado el nombre por triplicado. "startDateTime" es el nombre de la propiedad NSDate en mi clase personalizada. – markdorison

+2

El problema resultó estar en otra parte de mi código, así que consideré cerrar la pregunta, pero debido a la naturaleza útil de las respuestas a continuación, lo dejaré aquí porque creo que otros pueden encontrarlo útil. – markdorison

Respuesta

25

¿Está seguro de que las variables de instancia startDateTime de los eventos de nodo son no-nil?

Si no tiene uno ya, es posible añadir un (a medida) -description método para sus objetos de eventos de nodo que hace algo como esto:

- (NSString *)description { 
    return [NSString stringWithFormat:@"%@ - %@", 
        [super description], startDateTime]]; 
} 

Luego, en el código de clasificación log la matriz antes y después:

NSLog(@"nodeEventArray == %@", nodeEventArray); 
NSSortDescriptor *dateDescriptor = [NSSortDescriptor 
            sortDescriptorWithKey:@"startDateTime" 
               ascending:YES]; 
NSArray *sortDescriptors = [NSArray arrayWithObject:dateDescriptor]; 
NSArray *sortedEventArray = [nodeEventArray 
     sortedArrayUsingDescriptors:sortDescriptors]; 
NSLog(@"sortedEventArray == %@", sortedEventArray); 

Si los startDateTime 's son todos nil, entonces el antes y después de las matrices tendrán el mismo orden (ya que la operación de clasificación será igual al envío de todos los mensajes a -compare:nil, que básicamente no hace nada).

11

¿Has probado especificando el comparador NSDate?

Ej:

NSSortDescriptor *dateDescriptor = [NSSortDescriptor 
    sortDescriptorWithKey:@"startDateTime" 
    ascending:YES 
    selector:@selector(compare:)]; 

Esto debería hacer cumplir el uso del comparador correcta de la clase NSDate.

+1

Este cambio no pareció afectar mis resultados. – markdorison

11

Ok, sé que esto es un poco tarde, pero esta es la forma en que lo haría:

NSArray *sortedEventArray = [events sortedArrayUsingComparator:^NSComparisonResult(Event *event1, Event *event2) { 
    return [event1.startDateTime compare:event2.startDateTime]; 
}]; 

Obviamente, reemplace Evento con la clase de objeto personalizado. La ventaja de este enfoque es que está protegido contra futuras refactorizaciones. Si fuera a refactorizar y renombrar la propiedad startDateTime a otra cosa, Xcode probablemente no cambiaría la cadena que está pasando al descriptor de clasificación. De repente, tu código de clasificación se rompería/no haría nada.

+0

Estoy de acuerdo contigo. FYI sin embargo, pequeño error tipográfico. Es: "sortedArrayUsingComparator:" –

+0

Funciona como un amuleto, gracias. –

+0

@PaulEvans Estaba usando - [NSMutableArray sortUsingComparator:], como noté en mi comentario. Sin embargo, puedo cambiarlo para devolver una nueva matriz ordenada en línea con el ejemplo de OP. Gracias :) – slottermoser

0

Esto se puede conseguir de esta manera,

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:FALSE]; 

[self.Array sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]]; 
0

Se puede lograr de esta manera,

NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"anyDateField" ascending:YES]; 

NSMutableArray *arr = [[array sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]]mutableCopy]; 
Cuestiones relacionadas