¿Cómo clasifico un NSMutableArray con objetos personalizados?
Lo que quiero hacer parece bastante simple, pero no encuentro ninguna respuesta en la web. Tengo una NSMutableArray
serie de objetos y digamos que son objetos de 'Persona'. Quiero ordenar NSMutableArray
por Person.birthDate, que es un archivo NSDate
.
Creo que tiene algo que ver con este método:
NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(???)];
En Java haría que mi objeto implementara Comparable, o usaría Collections.sort con un comparador personalizado en línea... ¿cómo diablos se hace esto en Objective-C?
método de comparación
O implementas un método de comparación para tu objeto:
- (NSComparisonResult)compare:(Person *)otherObject {
return [self.birthDate compare:otherObject.birthDate];
}
NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(compare:)];
NSSortDescriptor (mejor)
o generalmente incluso mejor:
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
ascending:YES];
NSArray *sortedArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];
Puede ordenar fácilmente por varias claves agregando más de una a la matriz. También es posible utilizar métodos de comparación personalizados. Eche un vistazo a la documentación .
Bloques (¡brillantes!)
También existe la posibilidad de ordenar con un bloque desde Mac OS X 10.6 e iOS 4:
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(Person *a, Person *b) {
return [a.birthDate compare:b.birthDate];
}];
Actuación
Los -compare:
métodos basados en bloques serán bastante más rápidos, en general, que su uso, NSSortDescriptor
ya que este último se basa en KVC. La principal ventaja del NSSortDescriptor
método es que proporciona una forma de definir el orden de clasificación utilizando datos, en lugar de código, lo que facilita, por ejemplo, configurar las cosas para que los usuarios puedan ordenar NSTableView
haciendo clic en la fila del encabezado.
Ver el NSMutableArray
métodosortUsingFunction:context:
Necesitará configurar una función de comparación que tome dos objetos (de tipo Person
, ya que está comparando dos Person
objetos) y un parámetro de contexto .
Los dos objetos son sólo ejemplos de Person
. El tercer objeto es una cadena, por ejemplo @"birthDate".
Esta función devuelve un NSComparisonResult
: Devuelve NSOrderedAscending
si PersonA.birthDate
< PersonB.birthDate
. Volverá NSOrderedDescending
si PersonA.birthDate
> PersonB.birthDate
. Finalmente, volverá NSOrderedSame
si PersonA.birthDate
== PersonB.birthDate
.
Este es un pseudocódigo aproximado; necesitarás desarrollar lo que significa que una fecha sea "menos", "más" o "igual" que otra fecha (como comparar segundos desde la época, etc.):
NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
if ([firstPerson birthDate] < [secondPerson birthDate])
return NSOrderedAscending;
else if ([firstPerson birthDate] > [secondPerson birthDate])
return NSOrderedDescending;
else
return NSOrderedSame;
}
Si quieres algo más compacto, puedes usar operadores ternarios:
NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
return ([firstPerson birthDate] < [secondPerson birthDate]) ? NSOrderedAscending : ([firstPerson birthDate] > [secondPerson birthDate]) ? NSOrderedDescending : NSOrderedSame;
}
La inserción en línea quizás podría acelerar esto un poco, si lo haces con frecuencia.