2009-09-13 9 views
17

Was ist die beste Methode, um die NSFetchedResultsController Daten zu filtern? Muss ich es jedes Mal neu initialisieren, wenn sich der Text der Suchleiste ändert?NSFetchedResultsController mit Suche

Ich verwende einen UISearchDisplayControllers und ich bin der Umsetzung:

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

Thx.

+0

Wie haben Sie die Datenquellenmethoden der Tabellenansicht behandelt, damit die Tabellenansicht wissen kann, ob die gefilterte Liste angezeigt werden soll oder nicht? – CraigH

+1

Die Antwort hier ist sehr, sehr hilfreich http://stackoverflow.com/questions/4471289/how-to-filter-nsfetchedresultscontroller-coredata-mit-uisearchdisplaycontroll/4481896#4481896 – acecapades

+0

Hier ist, was ich getan habe: http: // stackoverflow .com/fragen/4471289/how-to-filter-nsfetchedresultscontroller-coredata-mit-uisearchdisplaycontrolle/4856118 # 4856118 –

Antwort

17

Wie ist Guy Antwort Code anders von der Frage? Soweit ich das erraten kann, wird die filterContentForSearchText: scope-Methode von den shouldReload-Methoden aufgerufen.

Wie auch immer, hier ist ein ähnlicher Code, den ich im CoreDataBooks-Beispiel hinzugefügt habe, um die Suche einzuschließen. Fügen Sie einen Search Display Controller in IB für das CoreDataBooks-Beispiel hinzu. Dann fügte ich Code RootViewController.m wie folgt hinzu:

- (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. Um Vivas zu beantworten, erstellt es mithilfe eines UISearchDisplayControllers automatisch eine neue Tabellenansicht zum Überlagern der gefilterten Liste. Sie können überprüfen, welches tableView wie in den Dokumenten gezeigt verwendet wird, aber im einfachsten Fall funktioniert es nur, weil der abgerufeneResultsController entweder eine gefilterte Version in der Tabellenansicht der Suche anzeigt oder alle Daten in Ihrer Tabellenansicht anzeigt.

+0

Immer noch seltsames Verhalten ... Objekte werden gefiltert, aber wenn ich in der Tabellenansicht nach unten scrollen, gibt es eine Ausnahme, weil fetchController kein Objekt bei einem bestimmten Index hat ... was kann falsch sein? bitte, help –

+0

Ich habe mein Problem herausgefunden ... wenn ich gefilterte Ergebnisse bekomme, werden sie in der Tabelle angezeigt, die auf die gleiche Weise konfiguriert ist, und wenn ich zu Zeile Nummer X scrolle, wo die reelle Anzahl von Zeilen kleiner als X ist ... was soll ich tun.. –

8

appearantly ist dies ein besserer Weg:

- (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

Ausfahrt (-1) ist ein bisschen hart. – 0xced

+5

Die Anwendung sagt, dass die Abrufanforderung nicht geändert werden sollte - sie sagen ausdrücklich, dass Sie das Prädikat nicht ändern sollten. –

+1

@RogerNolan Sind Sie sicher? Überprüfen Sie [NSFetchedResultsController-Klassenreferenz: Ändern der Abrufanforderung] (http://j.mp/z3W7QK). Diese drei Schritte funktionieren gut für mich, und ich modifiziere sogar das Prädikat der Abrufanforderung. – ma11hew28

Verwandte Themen