Deseo proporcionar una clasificación personalizada utilizando NSFetchedResultsController y NSSortDescriptor.Clasificación personalizada con NSFetchedResultController (subclase de NSSortDescriptor)
Como costumbre de clasificación a través de mensaje NSSortDescriptor - (id) initWithKey: ascendente: selector: no es posible (ver here), He intentado utilizar una clase derivada NSSortDescriptor con el fin de anular el compareObject: toObject: mensaje.
Mi problema es que compareObject: toObject: no siempre se llama. Parece que se llama solo cuando los datos ya están en la memoria. Existe una optimización de algún tipo que utiliza una ordenación basada en la base de datos en lugar de compareObject: toObject cuando los datos se recuperan de la tienda la primera vez. (ver here).
Mi pregunta es: ¿cómo obligar a NSFetchedResultscontroller a usar el objeto compareObject: toObject: para ordenar los datos? (y ¿funcionará con un gran conjunto de datos)
Una solución es utilizar una tienda binaria en lugar de una tienda sqlite, pero no quiero hacer eso.
Otra solución es:
-call performFetch para ordenar los datos a través de SQL (compareObject no llama)
-hacer una modificación de los datos e invertirla.
-call performRegreso nuevamente (compare se llama Objeto)
Funciona en mi caso, pero es un truco y no estoy seguro de que siempre funcione (especialmente con un gran conjunto de datos (mayor que el tamaño del lote)).
ACTUALIZADO: Puede reproducir con el ejemplo de CoreDataBooks.
En RootViewController.m, anadir este feo truco:
- (void)viewWillAppear:(BOOL)animated {
Book* book = (Book *)[NSEntityDescription insertNewObjectForEntityForName:@"Book"
inManagedObjectContext:[self fetchedResultsController].managedObjectContext];
[[self fetchedResultsController] performFetch:nil];
[[self fetchedResultsController].managedObjectContext deleteObject:book];
[self.tableView reloadData];
}
En RootViewController.m, reemplace el código descriptor de género con:
MySortDescriptor *myDescriptor = [[MySortDescriptor alloc] init];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:myDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
Añadir clase MySortDescriptor:
@implementation MySortDescriptor
-(id)init
{
if (self = [super initWithKey:@"title" ascending:YES selector:@selector(compare:)])
{
}
return self;
}
- (NSComparisonResult)compareObject:(id)object1 toObject:(id)object2
{
//set a breakpoint here
return [[object1 valueForKey:@"author" ] localizedCaseInsensitiveCompare:[object2 valueForKey:@"author" ] ];
}
//various overrides inspired by [this blog post][3]
- (id)copy
{
return [self copyWithZone:nil ];
}
- (id)mutableCopy
{
return [self copyWithZone:nil ];
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
return [self copyWithZone:zone ];
}
- (id)copyWithZone:(NSZone*)zone
{
return [[MySortDescriptor alloc] initWithKey:[self key] ascending:[self ascending] selector:[self selector]];
}
- (id)reversedSortDescriptor
{
return [[[MySortDescriptor alloc] initWithKey:[self key] ascending:![self ascending] selector:[self selector]] autorelease];
}
@end
¿Cómo está tratando de ordenar sus datos que NSSortDescriptor, o alguna combinación de múltiples NSSortDescriptors es insuficiente? – ImHuntingWabbits
Estoy tratando de ordenar puntos según su distancia desde un punto de referencia. Esperaba encapsular el punto de referencia como un ivar en un objeto derivado NSSortDescriptor. – FKDev
Hmm, eso suena como un problema interesante. Ciertamente parece que tendrás que tirar de los objetos en la memoria para ordenarlos. Podría tener un "punto de referencia" de propiedad en su entidad objetivo y una propiedad transitoria llamada distancia. Implementa la distancia para calcular la distancia entre el punto de referencia y la entidad objetivo, ordena la distancia. Aunque me gusta más tu idea de subclase. – ImHuntingWabbits