2009-09-13 4 views
17

Qual è la procedura migliore per filtrare i dati NSFetchedResultsController? devo inizializzarlo di nuovo ogni volta che cambia il testo della barra di ricerca?NSFetchedResultsController con ricerca

Sto usando un UISearchDisplayControllers e sto attuazione:

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString; 

Thx.

+0

Come è terminata la gestione dei metodi di origine dati della vista tabella in modo che la vista tabella sappia se visualizzare o meno l''elenco filtrato'? – CraigH

+1

La risposta qui è molto molto utile http://stackoverflow.com/questions/4471289/how-to-filter-nsfetchedresultscontroller-coredata-with-uisearchdisplaycontroll/4481896#4481896 – acecapades

+0

Ecco quello che ho fatto: http: // StackOverflow .com/questions/4471289/how-to-filter-nsfetchedresultscontroller-coredata-with-uisearchdisplaycontrolle/4856118 # 4856118 –

risposta

17

Come è codice di risposta di Guy diverso dalla questione? Per quanto posso immaginare, il metodo filterContentForSearchText: scope è chiamato dai metodi shouldReload?

In ogni caso, ecco un codice simile che ho aggiunto nell'esempio CoreDataBooks per includere la ricerca. Aggiungi un controller di visualizzazione di ricerca in IB per l'esempio di CoreDataBooks. Quindi ho aggiunto il codice a RootViewController.m come segue:

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { 
NSInteger searchOption = controller.searchBar.selectedScopeButtonIndex; 
return [self searchDisplayController:controller shouldReloadTableForSearchString:searchString searchScope:searchOption]; 
} 

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption { 
NSString* searchString = controller.searchBar.text; 
return [self searchDisplayController:controller shouldReloadTableForSearchString:searchString searchScope:searchOption]; 
} 

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString*)searchString searchScope:(NSInteger)searchOption { 

NSPredicate *predicate = nil; 
if ([searchString length]) 
    if (searchOption == 0) // full text, in my implementation. Other scope button titles are "Author", "Title" 
    predicate = [NSPredicate predicateWithFormat:@"title contains[cd] %@ OR author contains[cd] %@", searchString, searchString]; 
    else 
    // docs say keys are case insensitive, but apparently not so. 
    predicate = [NSPredicate predicateWithFormat:@"%K contains[cd] %@", [[controller.searchBar.scopeButtonTitles objectAtIndex:searchOption] lowercaseString], searchString]; 
[fetchedResultsController.fetchRequest setPredicate:predicate]; 

    NSError *error = nil; 
    if (![[self fetchedResultsController] performFetch:&error]) { 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    abort(); 
    }   

return YES; 
} 

PS. Per rispondere a Vivas, utilizzando un UISearchDisplayController, crea automaticamente una nuova vista tabella per sovrapporre l'elenco filtrato. Puoi verificare quale tabellaView viene utilizzata come mostrato nei documenti, ma nella configurazione più semplice funziona solo perché fetchedResultsController mostra una versione filtrata nella visualizzazione tabella della ricerca o mostra tutti i dati nella visualizzazione tabella.

+0

Comportamento ancora strano ... gli oggetti vengono filtrati, ma quando faccio scorrere verso il basso la vista tabella dà un'eccezione, perché fetchController non ha oggetti con un indice particolare ... cosa può essere sbagliato? per favore, aiuto –

+0

Ho capito il mio problema ... quando ottengo i risultati filtrati vengono visualizzati nella tabellaVisualizzazione configurata nello stesso modo e quando si scorre il numero X della riga dove il numero reale di righe è minore di X ... cosa dovrei.. –

8

Appearantly questo è un modo migliore:

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope 
{ 
    self.savedSearchTerm = searchText; 

    freshData = NO; 
    if (searchText !=nil) 
    { 
      NSPredicate *predicate =[NSPredicate predicateWithFormat:@"name contains[cd] %@", searchText]; 
      [fetchedResultsController.fetchRequest setPredicate:predicate]; 
    } 
    else 
    { 
      NSPredicate *predicate =[NSPredicate predicateWithFormat:@"All"]; 
      [fetchedResultsController.fetchRequest setPredicate:predicate]; 
    } 

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

    [self.tableView reloadData]; 

    // [searchBar resignFirstResponder]; 
    // [_shadeView setAlpha:0.0f]; 

} 
+29

exit (-1) è un po 'duro. – 0xced

+5

I documenti di appl dicono che la richiesta di recupero non deve essere modificata, in particolare dicono che non si dovrebbe modificare il predicato. –

+1

@RogerNolan Sei sicuro? Controlla [Riferimento classe NSFetchedResultsController: Modifica la richiesta di recupero] (http://j.mp/z3W7QK). Quei tre passaggi funzionano bene per me e modifico persino il predicato della richiesta di recupero. – ma11hew28