8

Attualmente sto cercando di popolare UITableView nel mio progetto da Core Data usando NSFetchedResultsController. Sto usando una ricerca personalizzata con un comparatore (anche se ho anche provato un selettore e ha avuto un problema identico):NSFetchedResultsController L'ordinamento personalizzato non viene chiamato

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; 

Quando entro in questa scheda, sono registrati in tutto il programma e ha scoperto che il NSFetchedResultsController fa nemmeno inserire il blocco comparatore durante il recupero. Lo ordina invece con un metodo di ordinamento predefinito.

Se elimino e aggiungo un oggetto con un oggettoName, tuttavia, esso immette il blocco comparatore e ordina correttamente la tabella.

Perché NSFetchedResultsController non esegue l'ordinamento utilizzando il comparatore finché non viene modificato il modello dell'oggetto gestito?

Note: Ho provato anche a disattivare la memorizzazione nella cache e/oa eseguire un recupero in viewDidLoad :, ma sembra che quante volte ho recuperato non importa, ma quando. Per qualche motivo utilizza solo il mio ordinamento dopo che il modello dell'oggetto è stato modificato.

risposta

8

ci sono un paio di cose Posso pensare. Innanzitutto, anche se questo potrebbe non essere il tuo problema, non puoi ordinare le proprietà transitorie. Ma più probabilmente è che quando si ordina in un modello supportato da un archivio SQL, il comparatore viene "compilato" in una query SQL e non tutte le funzioni Objective-C sono disponibili. In questo caso, avresti bisogno di ordinare in memoria dopo l'esecuzione del recupero.

MODIFICA: vedere questo doc, in particolare la sezione Predicati recupero e Descrittori di ordinamento.

+1

Non sono proprietà transitorie, ma l'altro suggerimento sembra essere il problema. L'unico problema è che mi sto affidando al controller fetchedresults per fornire i nomi delle sezioni e così via per la vista tabella, quindi l'ordinamento in memoria ogni volta sarebbe difficile (credo). Come consiglieresti di andare a riguardo? E la mia altra domanda sarebbe: perché il blocco del comparatore funziona dopo che il modello dell'oggetto è stato modificato? Grazie! –

+0

Beh, in realtà il problema più generale qui è che sto implementando le sezioni nella mia vista tabella, insieme a un indice di sezione. Metto qualsiasi oggetto che inizia con un numero in una sezione "123" (funziona), ma voglio che questa sezione sia in basso come l'app per iPod. Secondo le app di Apple, i numeri dovrebbero essere l'ultima opzione nel sectionIndex (sto usando UILocalizedIndexedCollation per generare gli indici delle sezioni). Sembra che non ci sia modo, comunque, di recuperare le sezioni in modo che i numeri durino. Sai di un modo più affidabile per farlo rispetto all'ordinamento personalizzato? –

+2

Solo un'ipotesi, ma penso che il blocco comparatore funzioni dopo che il modello oggetto è stato modificato perché il grafico è già in memoria. Ma questa è solo una supposizione. Il modo in cui si ordina manualmente, credo, è quello di sottoclasse NSArrayController, quindi si perderebbero i vantaggi di NSFetchedResultsController. Ma, come dici tu, il problema principale è che vuoi ordinare i numeri in fondo.In cima alla mia testa, direi di creare una proprietà di ordinamento sugli oggetti e usarla, ma non ho fatto abbastanza ordinamento personalizzato usando i descrittori di ordinamento. – Don

0

dispiace, ma ti è mancato la finale fetch parte per lo snippet di codice ?:

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

Non dimenticate di rilasciare la richiesta di troppo:

[fetchRequest release]; 
+0

No, non l'ho incluso nello snippet. Ho incluso l'intero metodo se questo lo rende più chiaro. –

1

Vedo lo stesso problema e un modo per aggirare il problema è modificare un oggetto, salvare la modifica, ripristinarla al suo valore originale e salvare di nuovo.

// 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]; 
    } 
} 
Problemi correlati