14

Ho creato un'app per iPhone utilizzando i dati principali.Come utilizzare NSFetchedResultsController e UISearchDisplayController

Prima di tutto, ha senso utilizzare un NSFetchedResultsController e un UISearchDisplayController insieme per recuperare il risultato? Consiglieresti qualcos'altro?

Ho cercato a lungo unendo un NSFetchedResultController e un UISearchDisplayController. Stavo pensando di impostare un NSPredicate nel metodo (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption per NSFetchedResultController di UIViewController. Ma non sta funzionando così bene.

Quindi, hai idea di come implementare una soluzione per il mio problema? Grazie per aver pubblicato risposte o collegamenti a buoni tutorial.

EDIT

Ecco il mio codice. I metodi UISearchDisplayDelegate chiamano il metodo (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope che dovrebbe impostare il predicato in NSFetchedResultController. Ho anche aggiunto il codice di NSFetchedResultController.

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString 
{ 
    [self filterContentForSearchText:searchString scope: 
    [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]]; 

    // Return YES to cause the search result table view to be reloaded. 
    return YES; 
} 


- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption 
{ 
    [self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope: 
    [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]]; 

    // Return YES to cause the search result table view to be reloaded. 
    return YES; 
} 


- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope 
{ 
    NSString *query = self.searchDisplayController.searchBar.text; 
    if (query && query.length) { 
     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Name contains[cd] %@", query]; 
     [fetchedResultsController.fetchRequest setPredicate:predicate]; 
    } 

    NSError *error = nil; 
    if (![[self fetchedResultsController] performFetch:&error]) { 
     // Handle error 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     exit(-1); // Fail 
    } 

} 


- (NSFetchedResultsController *)fetchedResultsController { 

    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:@"Event" inManagedObjectContext:managedObjectContext]; 
    [fetchRequest setEntity:entity]; 

    // Set the batch size to a suitable number. 
    [fetchRequest setFetchBatchSize:20]; 

    // Edit the sort key as appropriate. 
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; 

    [fetchRequest setSortDescriptors:sortDescriptors]; 

    // Edit the section name key path and cache name if appropriate. 
    // nil for section name key path means "no sections". 
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"]; 
    aFetchedResultsController.delegate = self; 
    self.fetchedResultsController = aFetchedResultsController; 

    [aFetchedResultsController release]; 
    [fetchRequest release]; 
    [sortDescriptor release]; 
    [sortDescriptors release]; 

    return fetchedResultsController; 
} 

risposta

21

Guardare il codice, è proprio lì. Ho riscontrato problemi con questo metodo per modificare la ricerca. La correzione: cancella la cache!

Supponiamo di aver avviato il controller dei risultati recuperato come segue. Nota la proprietà cacheName.

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:[self fetchRequest] managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"UserSearch"]; 

Come si cambia il predicato, è sufficiente aggiungere:

[NSFetchedResultsController deleteCacheWithName:@"UserSearch"]; 

Come per magia, che funzionerà bene.

Si desidera inoltre monitorare quando il controller del display di ricerca interrompe la ricerca e cancellare il predicato.

Anche se questo thread sembra morto, l'ho trovato su google, quindi forse qualcuno là fuori userà questo. :)

+1

Questa soluzione funziona, ma è piuttosto costosa, costringendo il controller dei risultati recuperato in numerosi viaggi nell'archivio permanente. Inoltre, se non intendi utilizzare la cache, perché specificarne una? Basta passare nil. Una soluzione molto migliore, tuttavia, è ciò che @psuedonick suggerisce: Lascia che il fetchedResultsController esegua le operazioni migliori, ovvero gestisce i risultati recuperati e usa filteredArrayUsingPredicate: su fetchedObjects per popolare filteredListContent. –

+2

Per chiarire, se si utilizza la soluzione che descrivo, si * dovrebbe * specificare una cache: il controller dei risultati recuperato ne avrà bisogno per archiviare gli oggetti fetched in modo che possano essere efficacemente cercati da filteredArrayUsingPredicate: –

+0

Grazie Elise, penso che la tua via sia la strada da percorrere Concluderò i passaggi per implementare il controller di visualizzazione della ricerca in un controller di visualizzazione tabella in un altro post successivo. Mi ci vuole così tanto tempo per cercare una buona pratica su questo argomento. – Philip007

1

Sembra che siate interessati solo al recupero e alla visualizzazione di oggetti. In questo caso, NON si utilizza un controller di visualizzazione di ricerca. Il controller del display di ricerca viene utilizzato con una barra di ricerca per aiutare a consentire le ricerche di testo inserite dall'utente nei tuoi contenuti.

In genere si utilizza un controller dei risultati recuperato per facilitare l'implementazione dell'origine dati della vista tabella e dei metodi di delega. Inoltre, puoi creare e utilizzare una richiesta di recupero per il tuo controller dei risultati recuperato. Questa è tutta la piastra della caldaia (vedi il codice template fornito da Apple quando crei un nuovo progetto con l'opzione "Usa i dati principali per lo storage" selezionata).

È nella richiesta di recupero che è possibile creare e specificare un predicato. Ciò consentirà di filtrare gli oggetti visualizzati nella tabella. Ad esempio:

+0

Beh, non ho detto chiaramente che in realtà sto implementando un po ' ricerca. Ho già provato a impostare il predicato in NSFetchedResultsController per filtrare i risultati, esattamente come il codice postato, ma non succede nulla, non vengono trovati oggetti. Qualche idea sul perché il predicato non funziona? È solo un semplice confronto tra la stringa di ricerca e il nome dell'oggetto. Grazie per l'aiuto – burki

+0

È necessario aggiungere dettagli sul predicato o fare una nuova domanda al riguardo. Inoltre, è sempre bene mostrare il codice che si sta utilizzando quando si fanno domande. – gerry3

7

In base ai documenti, si desidera filtrare i risultati in un array utilizzando un predicato o reinizializzare il recuperatoResultsController.

Importante: Non è necessario modificare il prendere richiesta dopo aver inizializzato il controller.Per esempio , non è necessario modificare il predicato o gli ordinamenti.

- NSFetchedResultsController

(. Mi piacerebbe commentare la risposta di inattività, ma io sono il karma-less)

Problemi correlati