14

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; 
} 

Répondre

21

En regardant votre code, c'est là. J'ai rencontré des problèmes en utilisant cette méthode pour changer la recherche. La solution: vider votre cache!

Dites que vous avez initialisé votre contrôleur de résultat récupéré comme suit. Notez la propriété cacheName.

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

Comme vous changez prédicat, ajoutez simplement:

[NSFetchedResultsController deleteCacheWithName:@"UserSearch"]; 

Comme par magie, cela fonctionnera bien.

Vous voudrez également surveiller quand le contrôleur d'affichage de recherche mettra fin à sa recherche et effacer votre prédicat.

Bien que ce fil semble mort, je l'ai trouvé sur google, alors peut-être que quelqu'un va l'utiliser. :)

+1

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. –

+2

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: –

+0

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

1

Il semble que vous soyez simplement intéressé par l'extraction et l'affichage d'objets. Dans ce cas, vous n'utilisez PAS de contrôleur d'affichage de recherche. Le contrôleur d'affichage de recherche est utilisé avec une barre de recherche pour faciliter la recherche de texte dans votre contenu.

Généralement, vous utilisez un contrôleur de résultats récupérés pour faciliter l'implémentation de la source de données de vue de table et des méthodes de délégation. En outre, vous créez et utilisez une requête d'extraction pour votre contrôleur de résultats récupérés. Il s'agit d'une plaque de chaudière (voir le code de modèle fourni par Apple lorsque vous créez un nouveau projet avec l'option «Utiliser les données de base pour le stockage» sélectionnée).

C'est dans la requête d'extraction que vous pouvez créer et spécifier un prédicat. Cela vous permettra de filtrer les objets que votre table affiche. Par exemple:

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

Eh bien, je n'ai pas dit clairement que je suis mise en œuvre en fait un peu chercher. J'ai déjà essayé de définir le prédicat dans le NSFetchedResultsController pour filtrer les résultats, exactement comme votre code posté, mais rien ne se passe, aucun objet n'est trouvé. Une idée de pourquoi le prédicat ne fonctionne pas? C'est juste une simple comparaison entre la chaîne de recherche et le nom des objets. Merci pour votre aide – burki

+0

Vous devez ajouter des détails sur le prédicat ou poser une nouvelle question à ce sujet. En outre, il est toujours bon de montrer le code que vous utilisez en posant des questions. – gerry3

7

Selon les documents, vous souhaiterez filtrer les résultats dans un tableau à l'aide d'un prédicat ou réinitialiser le paramètre fetchedResultsController.

Important: Vous ne devez pas modifier le demande de récupération après que vous avez initialisées le contrôleur.Pour l'exemple , vous ne devez pas modifier le prédicat ou les ordres de tri.

- NSFetchedResultsController

(. Je commente la réponse au ralenti, mais je suis karma moins)

Questions connexes