2009-09-13 16 views
17

¿Cuál es la mejor práctica para filtrar los datos NSFetchedResultsController? ¿necesito volver a inicializarlo cada vez que cambie el texto de la barra de búsqueda?NSFetchedResultsController con la búsqueda

estoy usando un UISearchDisplayControllers y estoy de aplicación:

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

Thx.

+0

Cómo acabaste el manejo de los métodos vista de tabla de fuente de datos para que la vista de tabla sabrá si se muestra la 'lista filtrada' o no? – CraigH

+1

La respuesta aquí es muy útil http://stackoverflow.com/questions/4471289/how-to-filter-nsfetchedresultscontroller-coredata-with-uisearchdisplaycontroll/4481896#4481896 – acecapades

+0

Esto es lo que hice: http: // stackoverflow .com/preguntas/4471289/cómo-a-filter-nsfetchedresultscontroller-coredata-con-uisearchdisplaycontrolle/4856118 # 4856118 –

Respuesta

17

Cómo es código de respuesta del individuo diferente de la cuestión? Por lo que puedo adivinar, el método filterContentForSearchText: scope es llamado por los métodos shouldReload?

De todos modos, aquí hay un código similar que he añadido en la muestra CoreDataBooks para incluir la búsqueda. Agregue un Controlador de visualización de búsqueda en IB para el ejemplo de CoreDataBooks. Luego agregué código a RootViewController.m de la siguiente manera:

- (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. Para responder a Vivas, usando un UISearchDisplayController crea una nueva vista de tabla automáticamente para superponer la lista filtrada. Puede verificar qué TableView se está utilizando como se muestra en los documentos, pero en la configuración más simple simplemente funciona porque fetchedResultsController muestra una versión filtrada en la vista de tabla de la búsqueda o muestra todos los datos en su vista de tabla.

+0

Conducta aún extraña ... los objetos sí se filtran, pero cuando me desplazo hacia abajo en la vista de tabla se da una excepción, porque fetchController no tiene un objeto en un índice particular ... ¿qué puede estar mal? por favor, ayuda –

+0

Descubrí mi problema ... cuando obtengo los resultados filtrados se muestran en la tabla vista configurada de la misma manera y cuando me desplazo al número de fila X donde el número real de filas es menor que X ... qué deberia hacer.. –

8

appearantly esta es una mejor manera:

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

salida (-1) es un poco duro. – 0xced

+5

Los documentos appl dicen que la solicitud de búsqueda no se debe modificar; específicamente dicen que no se debe cambiar el predicado. –

+1

@RogerNolan ¿Estás seguro? Consulte [NSFetchedResultsController Class Reference: Modifying the Fetch Request] (http://j.mp/z3W7QK). Esos tres pasos funcionan bien para mí, e incluso modifico el predicado de la solicitud de búsqueda. – ma11hew28

Cuestiones relacionadas