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;
}
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. –
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: –
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