8

Actualmente estoy tratando de llenar una UITableView en mi proyecto desde Core Data utilizando NSFetchedResultsController. Estoy usando una búsqueda personalizada con un comparador (aunque también he intentado un selector y tenía un problema idéntico):NSFetchedResultsController clasificación personalizada sin llamarse

if (fetchedResultsController != nil) { 
     return fetchedResultsController; 
    } 

    /* 
    Set up the fetched results controller. 
    */ 
    // Create the fetch request for the entity. 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    // Edit the entity name as appropriate. 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Object" inManagedObjectContext:self.managedObjectContext]; 
    [fetchRequest setEntity:entity]; 

    // Set the batch size to a suitable number. 
    [fetchRequest setFetchBatchSize:20]; 
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"objectName" ascending:YES comparator:^(id s1, id s2) { 
      NSLog(@"Comparator"); 
     //custom compare here with print statement 
    }]; 
    NSLog(@"Sort Descriptor Set"); 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Object" inManagedObjectContext:self.managedObjectContext]; 
    [fetchRequest setEntity:entity]; 
    [fetchRequest setSortDescriptors:sortDescriptors]; 

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"firstLetterOfObject" cacheName:@"Objects"]; 
    [aFetchedResultsController release]; 
    [fetchRequest release]; 
    [sortDescriptor release]; 
    [sortDescriptors release]; 
    if (![fetchedResultsController performFetch:&error]) { 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); 
    } 

    return fetchedResultsController; 

Cuando entro en esta ficha, he conectado todo el programa y se encontró que el NSFetchedResultsController hace ni siquiera ingrese el bloque de comparación cuando vaya a buscar. En cambio, lo ordena con algún método de clasificación predeterminado.

Sin embargo, si borro y agrego un Objeto con un objectName, ingresa el bloque de comparación y ordena correctamente la tabla.

¿Por qué NSFetchedResultsController no ordena utilizando el comparador hasta que se modifique el modelo de objetos gestionados?

Notas: He intentado también apagar el almacenamiento en caché, y/o realizar una búsqueda en viewDidLoad :, pero parece que no importa cuántas veces busco, sino cuándo. Por alguna razón, solo utiliza mi clasificación después de que se modificó el modelo de objetos.

Respuesta

8

Hay un par de cosas Puedo pensar en. En primer lugar, aunque este no sea su problema, no puede ordenar las propiedades transitorias. Pero lo más probable es que al ordenar en un modelo respaldado por un almacén de SQL, el comparador se "compila" a una consulta SQL, y no todas las funciones de Objective-C están disponibles. En este caso, necesitaría ordenar en la memoria después de realizar la búsqueda.

EDITAR: Consulte este doc, específicamente la sección Obtener predicados y ordenar descriptores.

+1

No son propiedades transitorias, pero su otra sugerencia definitivamente parece que podría ser el problema. El único problema es que estoy confiando en el control de resultados fetched para proporcionar los nombres de sección y tal a la vista de tabla, por lo que clasificar en la memoria cada vez sería difícil (creo). ¿Cómo recomendarías hacerlo? Y mi otra pregunta sería ¿por qué el bloque de comparación funciona después de que se modificó el modelo de objetos? ¡Gracias! –

+0

Bueno, en realidad, el problema más general aquí es que estoy implementando secciones en mi vista de tabla, junto con un índice de sección. Pongo cualquier objeto comenzando con un número en la sección "123" (esto funciona), pero quiero que esta sección esté en la parte inferior como la aplicación del iPod. De acuerdo con las aplicaciones de Apple, los números deberían ser la última opción en sectionIndex (estoy usando UILocalizedIndexedCollation para generar los índices de sección). Sin embargo, parece que no hay forma de obtener las secciones para que los números sean los últimos. ¿Conoces una forma más confiable de hacer esto que la clasificación personalizada? –

+2

Es solo una suposición, pero creo que el bloque de comparación funciona después de que se modificó el modelo de objetos porque el gráfico ya está en la memoria. Pero eso es solo una suposición. La forma en que podría ordenar manualmente, creo, es la subclase NSArrayController, por lo que perdería los beneficios de NSFetchedResultsController. Pero, como dices, el problema de raíz es que quieres ordenar los números hasta el final.Por encima de todo, diría crear una propiedad de orden de clasificación en tus objetos y usar eso, pero no he hecho suficiente clasificación personalizada usando descripciones de ordenamiento. – Don

0

Lo sentimos, pero faltó a buscar a la última parte de su fragmento de código ?:

NSError *error; 
BOOL success = [aFetchedResultsController performFetch:&error]; 

No se olvide de liberar la solicitud también:

[fetchRequest release]; 
+0

No, simplemente no lo incluí en el fragmento. He incluido todo el método si eso lo aclara. –

1

Veo el mismo problema y una forma de evitarlo es modificar un objeto, guardar el cambio, restaurarlo a su valor original y guardar de nuevo.

// try to force an update for correct initial sorting bug 
NSInteger count = [self.fetchedResultsController.sections count]; 
if (count > 0) { 
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:0]; 
    count = [sectionInfo numberOfObjects]; 
    if (count > 0) { 
     NSManagedObject *obj = [self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; 
     NSString *name = [obj valueForKey:@"name"]; 
     [obj setValue:@"X" forKey:@"name"]; 
     // Save the context. 
     [self saveContext]; 
     [obj setValue:name forKey:@"name"]; 
     // Save the context. 
     [self saveContext]; 
    } 
} 
Cuestiones relacionadas