14

He estado creando una aplicación para iPhone usando Core Data.Cómo usar NSFetchedResultsController y UISearchDisplayController

En primer lugar, ¿tiene sentido utilizar un NSFetchedResultsController y un UISearchDisplayController juntos para obtener el resultado? ¿Recomendarías algo más?

He estado intentando bastante tiempo combinando un NSFetchedResultController y un UISearchDisplayController. He estado pensando en establecer un NSPredicate en el método (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption en NSFetchedResultController del UIViewController. Pero esto no está funcionando tan bien.

Entonces, ¿tiene alguna idea de cómo implementar una solución para mi problema? Gracias por publicar respuestas o enlaces a buenos tutoriales.

EDIT

Aquí está mi código. Los métodos UISearchDisplayDelegate llaman al método (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope que debe establecer el predicado en NSFetchedResultController. También agregué el código del 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; 
} 

Respuesta

21

Echando un vistazo a su código, está ahí. Me encontré con problemas con este método para cambiar la búsqueda. La solución: ¡borre su caché!

Supongamos que ha iniciado el controlador de resultados obtenido de la siguiente manera. Tenga en cuenta la propiedad cacheName.

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

A medida que cambia su predicado, sólo tiene que añadir:

[NSFetchedResultsController deleteCacheWithName:@"UserSearch"]; 

igual que la magia, que funcionará muy bien.

También querrá monitorear cuándo el controlador de visualización de búsqueda finalizará su búsqueda y borrará su predicado.

Aunque este hilo parece estar muerto, lo encontré en Google, por lo que quizás alguien de allí lo use. :)

+1

Esta solución funciona, pero es bastante costosa, lo que obliga al controlador de resultados obtenidos a realizar numerosos viajes a la tienda persistente. Además, si no vas a usar el caché, ¿por qué especificar uno? Solo pasa nil. Una solución mucho mejor, sin embargo, es a lo que @psuedonick insinúa: deje el control de resultados fetched para hacer lo que mejor hace, es decir, administre los resultados obtenidos, y use filteredArrayUsingPredicate: en fetchedObjects para completar el filtradoListContent. –

+2

Para aclarar, si utiliza la solución que describo, * debe * especificar una caché: el controlador de resultados obtenidos necesitará que almacene los objetos fetch para que puedan ser efectivamente buscados por filteredArrayUsingPredicate: –

+0

Gracias, Elise, creo que su camino es el camino a seguir. Concluiré los pasos para implementar el controlador de visualización de búsqueda en un controlador de vista de tabla en otra publicación posterior. Me lleva mucho tiempo buscar las mejores prácticas en este tema. – Philip007

1

Parece que solo está interesado en buscar y mostrar objetos. En este caso, NO usa un controlador de visualización de búsqueda. El controlador de visualización de búsqueda se utiliza con una barra de búsqueda para ayudar a permitir búsquedas de texto ingresadas por el usuario de su contenido.

Normalmente utiliza un controlador de resultados obtenido para ayudar en la implementación de la fuente de datos de la vista de tabla y delegar métodos. Además, crea y usa una solicitud de recuperación para su controlador de resultados obtenidos. Esto es todo placa de caldera (consulte el código de plantilla proporcionado por Apple cuando crea un nuevo proyecto con la opción "Usar datos principales para almacenamiento" seleccionada).

Es en la solicitud de búsqueda que puede crear y especificar un predicado. Esto le permitirá filtrar los objetos que muestra su tabla. Por ejemplo:

// only fetch objects with myAttribute set to someValue 
NSPredicate *pred = [NSPredicate predicateWithFormat:@"myAttribute == %@",someValue]; 
[fetchRequest setPredicate:pred]; 
+0

Bueno, no he mencionado claramente que en realidad estoy implementando un poco buscar. Ya he intentado establecer el predicado en NSFetchedResultsController para filtrar los resultados, exactamente como el código publicado, pero no ocurre nada, no se encuentran objetos. ¿Alguna idea de por qué el predicado no funciona? Es solo una comparación simple entre la cadena de búsqueda y el nombre de los objetos. Gracias por su ayuda – burki

+0

Debe agregar detalles sobre el predicado o hacer una nueva pregunta al respecto. Además, siempre es bueno mostrar el código que está utilizando al hacer preguntas. – gerry3

7

De acuerdo con los documentos, querrá filtrar los resultados en una matriz utilizando un predicado o reinicializar el control de resultados fetched.

Importante: No se debe modificar el petición de recuperación después de tener inicializar el controlador.Para el ejemplo , no debe cambiar el predicado o los ordenamientos.

- NSFetchedResultsController

(. Me comentar sobre la respuesta de inactividad, pero estoy karma-menos)

Cuestiones relacionadas