J'essaie d'implémenter le code de recherche dans mon application iPhone basée sur CoreData. Je ne sais pas trop comment procéder. L'application dispose déjà d'un NSFetchedResultsController avec un prédicat pour récupérer les données pour le TableView principal. Je veux m'assurer que je suis sur la bonne voie avant de changer trop de code. Je suis confus parce que beaucoup d'exemples sont basés sur des tableaux au lieu de CoreData.
Voici quelques questions:
Dois-je avoir un deuxième NSFetchedResultsController qui récupère uniquement les éléments correspondants ou puis-je utiliser le même que le TableView principal?
Si j'utilise le même, est-ce aussi simple que de vider le cache FRC, puis de modifier le prédicat dans la méthode handleSearchForTerm: searchString? Le prédicat doit-il contenir le prédicat initial ainsi que les termes de recherche ou se souvient-il qu'il a utilisé un prédicat pour récupérer des données en premier lieu?
Comment revenir aux résultats originaux? Dois-je simplement définir le prédicat de recherche sur nil? Cela ne tuera-t-il pas le prédicat original qui a été utilisé pour récupérer les résultats FRC en premier lieu?
Si quelqu'un a des exemples de code utilisant la recherche avec le FRC, je l'apprécierais grandement!
Réponses:
En fait, je viens de l'implémenter sur l'un de mes projets (votre question et l'autre mauvaise réponse indiquaient quoi faire). J'ai essayé la réponse de Sergio mais j'ai eu des problèmes d'exception lors de l'exécution sur un appareil.
Oui, vous créez deux contrôleurs d'extraction de résultats: un pour l'affichage normal et un autre pour la vue de table de UISearchBar.
Si vous n'utilisez qu'un seul FRC (NSFetchedResultsController), l'UITableView d'origine (et non la vue de la table de recherche active lors de la recherche) aura peut-être des rappels appelés pendant que vous recherchez et essayez d'utiliser incorrectement la version filtrée de votre FRC et vous verrez des exceptions jeté sur un nombre incorrect de sections ou de lignes dans les sections.
Voici ce que j'ai fait: J'ai deux FRC disponibles en tant que propriétés fetchedResultsController et searchFetchedResultsController. Le searchFetchedResultsController ne doit pas être utilisé sauf s'il y a une recherche (lorsque la recherche est annulée, vous pouvez voir ci-dessous que cet objet est libéré). Toutes les méthodes UITableView doivent déterminer la vue de table qu'elle interrogera et le FRC applicable à partir duquel extraire les informations. Les méthodes de délégué FRC doivent également déterminer la tableView à mettre à jour.
Il est surprenant de constater à quel point cela est un code standard.
Bits pertinents du fichier d'en-tête:
bits pertinents du fichier d'implémentation:
J'ai créé une méthode utile pour récupérer le FRC correct lorsque vous travaillez avec toutes les méthodes UITableViewDelegate / DataSource:
Déléguer des méthodes pour la barre de recherche:
assurez-vous que vous utilisez la vue de table correcte lors de l'obtention des mises à jour des méthodes de délégué FRC:
Autres informations de vue:
Code de création FRC:
la source
searchFetchedResultsController
surnil
chaque fois que le texte de recherche change.cellForRowAtIndexPath
, ne devriez-vous pas obtenir la cellule deself.tableView
quelqu'un comme quelqu'un l'a indiqué dans cette question SO? Si vous ne le faites pas, la cellule personnalisée ne s'affiche pas.Certains ont fait remarquer que cela pouvait être fait avec un seul
NSFetchedResultsController
. C'est ce que j'ai fait, et voici les détails. Cette solution suppose que vous souhaitiez simplement filtrer le tableau et conserver tous les autres aspects (ordre de tri, disposition des cellules, etc.) des résultats de la recherche.Tout d'abord, définissez deux propriétés dans votre
UITableViewController
sous - classe (avec les @synthesize et dealloc appropriés, le cas échéant):Deuxièmement, initialisez la barre de recherche dans la
viewDidLoad:
méthode de votreUITableViewController
sous-classe:Troisièmement, implémentez les
UISearchDisplayController
méthodes de délégué comme ceci:Enfin, dans la
fetchedResultsController
méthode changez leNSPredicate
dépendant siself.searchString
est défini:la source
Il m'a fallu quelques essais pour que cela fonctionne ...
Ma clé de compréhension a été de réaliser qu'il y a deux tablesViews à l'œuvre ici. Un géré par mon viewcontroller et un géré par le searchviewcontroller et ensuite je pourrais tester pour voir lequel est actif et faire la bonne chose. La documentation a également été utile:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UISearchDisplayController_Class/Reference/Reference.html
Voici ce que j'ai fait -
Ajout du drapeau searchIsActive:
Ajout de la synthèse dans le fichier d'implémentation.
Ensuite, j'ai ajouté ces méthodes pour rechercher:
Puis dans controllerWillChangeContent:
Et controllerDidChangeContent:
Et supprimez le cache lors de la réinitialisation du prédicat.
J'espère que cela t'aides.
la source
if ( [self.tableView isEqual:self.searchDisplayController.searchResultsTableView] ) { ... }
J'ai fait face à la même tâche et j'ai trouvé LE MOYEN LE PLUS SIMPLE pour le résoudre. En bref: vous devez définir une autre méthode, très similaire à celle
-fetchedResultsController
avec un prédicat composé personnalisé.Dans mon cas personnel, je
-fetchedResultsController
ressemble à ceci:Comme vous pouvez le voir, je cherche les clients d'une agence filtrés par
agency.server_id
prédicat. En conséquence, je récupère mon contenu dans untableView
(tout lié à la mise en œuvre detableView
et lefetchedResultsController
code est assez standard) également. Pour implémenter,searchField
je définis uneUISearchBarDelegate
méthode déléguée. Je le déclenche avec la méthode de recherche, disons-reloadTableView
:et bien sûr la définition de
-reloadTableView
:Ce groupe de code est très similaire au premier, "standard"
-fetchedResultsController
MAIS à l' intérieur de l'instruction if-else voici:+andPredicateWithSubpredicates:
- en utilisant cette méthode, nous pouvons définir un prédicat pour enregistrer les résultats de notre première extraction principale dans letableView
+orPredicateWithSubpredicates
- en utilisant cette méthode, nous filtrons l'extraction existante par requête de recherche à partir desearchBar
À la fin, je mets un tableau de prédicats en tant que prédicat composé pour cette extraction particulière. AND pour les prédicats requis, OU pour facultatif.
Et c'est tout! Vous n'avez rien d'autre à mettre en œuvre. Bon codage!
la source
Utilisez-vous une recherche en direct?
Si vous n'êtes PAS, vous voulez probablement un tableau (ou un NSFetchedResultsController) avec les recherches précédentes que vous avez utilisées, lorsque l'utilisateur appuie sur "recherche", vous dites à votre FetchedResults de changer son prédicat.
Dans tous les cas, vous devrez reconstruire vos FetchedResults à chaque fois. Je recommande d'utiliser un seul NSFetchedResultsController, car vous devrez beaucoup dupliquer votre code et vous n'avez pas besoin de gaspiller de la mémoire dans quelque chose que vous ne montrez pas.
Assurez-vous simplement que vous avez une variable NSString "searchParameters" et que votre méthode FetchedResults la reconstruit pour vous si nécessaire, en utilisant les paramètres de recherche si disponibles, vous devez simplement faire:
Voici un code simple:
la source
Swift 3.0, UISearchController, NSFetchedResultsController et Core Data
Ce code fonctionnera sur Swift 3.0 avec
Core Data
! Vous aurez besoin d'une méthode de délégué unique et de quelques lignes de code pour filtrer et rechercher des objets à partir du modèle. Rien ne sera nécessaire si vous avez implémenté toutes les méthodesFRC
et leursdelegate
méthodessearchController
.La
UISearchResultsUpdating
méthode du protocoleC'est tout! J'espère que cela vous aide! Merci
la source
SWIFT 3.0
Utilisez un textField, UISearchDisplayController est obsolète à partir d'iOS 8, vous devrez utiliser un UISearchController. Au lieu de vous occuper du contrôleur de recherche, pourquoi ne créez-vous pas votre propre mécanisme de recherche? Vous pouvez le personnaliser davantage et avoir plus de contrôle dessus, sans avoir à vous soucier de la modification et / ou de la désapprobation de SearchController.
Cette méthode que j'utilise fonctionne très bien et ne nécessite pas beaucoup de code. Cependant, vous devez utiliser Core Data et implémenter NSFetchedResultsController.
Tout d'abord, créez un TextField et enregistrez-le avec une méthode:
Créez ensuite votre méthode textFieldDidChange, décrite dans le sélecteur lors de l'ajout de la cible:
Ensuite, vous voulez filtrer la liste dans la
filterList()
méthode à l'aide du prédicat NSPredicate ou NSCompound si elle est plus complexe. Dans ma méthode filterList, je filtre en fonction du nom de l'entité et du nom de l'objet "subCategories" d'entités (une relation un à plusieurs).la source
Je pense que Luka a une meilleure approche pour cela. Voir LargeDataSetSample et sa raison
Il n'utilise pas
FetchedResultsController
, mais utilise le cache lors de la recherche, les résultats de la recherche apparaissent donc beaucoup plus rapidement lorsque l'utilisateur tape plus dans SearchBarJ'ai utilisé son approche dans mon application et cela fonctionne bien. Souvenez-vous également que si vous souhaitez travailler avec l'objet Model, rendez-le aussi simple que possible, voir ma réponse sur setPropertiesToFetch
la source
Voici une façon de gérer fetchedResults avec plusieurs ensembles de données qui est à la fois assez simple et générale pour s'appliquer presque partout. Saisissez simplement vos principaux résultats dans un tableau lorsqu'une condition est présente.
Interrogez le tableau en le parcourant en boucle ou selon ce que vous désirez afin de créer un sous-ensemble de vos principaux fetchedResults. Et maintenant, vous pouvez utiliser l'ensemble complet ou le sous-ensemble lorsqu'une condition est présente.
la source
J'ai beaucoup aimé l'approche de @Josh O'Connor où il n'utilise pas de fichier
UISearchController
. Ce contrôleur (Xcode 9) a toujours un bogue de mise en page que beaucoup tentent de contourner.Je suis revenu à utiliser un
UISearchBar
au lieu d'unUITextField
, et cela fonctionne très bien. Mon exigence pour la recherche / filtre est de produire un fichierNSPredicate
. Ceci est transmis au FRC:...
Enfin, connectez SearchBar à son délégué.
J'espère que cela aide les autres
la source
Approche simple pour filtrer UITableView existant à l'aide de CoreData et qui est déjà trié comme vous le souhaitez.
Cela m'a littéralement trop de 5 minutes pour configurer et travailler.
J'avais une
UITableView
utilisation existanteCoreData
remplie de données d'iCloud et qui a des interactions utilisateur assez compliquées et je ne voulais pas avoir à reproduire tout cela pour unUISearchViewController
. J'ai pu simplement ajouter un prédicat à l'existantFetchRequest
déjà utilisé par leFetchResultsController
et qui filtre les données déjà triées.la source