J'ai créé une application iPhone en utilisant des données de base.Comment utiliser NSFetchedResultsController et UISearchDisplayController
Tout d'abord, est-il logique d'utiliser un NSFetchedResultsController et un UISearchDisplayController ensemble pour récupérer le résultat? Recommanderiez-vous quelque chose d'autre?
J'ai essayé assez longtemps de combiner un NSFetchedResultController et un UISearchDisplayController. J'ai pensé à placer un NSPredicate dans la méthode (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
au NSFetchedResultController du UIViewController. Mais ça ne marche pas très bien. Donc, avez-vous une idée de la façon de mettre en œuvre une solution à mon problème? Merci déjà d'avoir posté des réponses ou des liens vers de bons tutoriels.
EDIT
Voici mon code. Les méthodes UISearchDisplayDelegate appellent la méthode (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
qui doit définir le prédicat dans NSFetchedResultController. J'ai également ajouté le code de 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;
}
Cette solution fonctionne, mais elle est plutôt coûteuse, obligeant le contrôleur de résultats récupérés à effectuer de nombreux déplacements dans le magasin persistant. De plus, si vous n'utilisez pas le cache, pourquoi en spécifier un? Il suffit de passer rien. Une meilleure solution, cependant, est ce que @psuedonick suggère: Laissez le fetchedResultsController faire ce qu'il fait le mieux, à savoir gérer les résultats récupérés, et utiliser filteredArrayUsingPredicate: sur fetchedObjects pour remplir le filteredListContent. –
Pour clarifier, si vous utilisez la solution que je décris, vous * devez * spécifier un cache: le contrôleur de résultats récupérés en aura besoin pour stocker les fetchedObjects afin qu'ils puissent être efficacement recherchés par filteredArrayUsingPredicate: –
Merci Elise, je pense que votre chemin est le chemin à parcourir. Je vais conclure les étapes pour implémenter le contrôleur d'affichage de recherche dans un contrôleur de vue de table dans un autre post plus tard. Il me faut tellement de temps pour chercher une meilleure pratique à ce sujet. – Philip007