Я пытаюсь реализовать поисковый код в своем приложении для iPhone на основе CoreData. Я не уверен, как поступить. В приложении уже есть NSFetchedResultsController с предикатом для извлечения данных для основного TableView. Я хочу убедиться, что я на правильном пути, прежде чем менять слишком много кода. Я запутался, потому что многие примеры основаны на массивах, а не на CoreData.
Вот несколько вопросов:
Нужен ли мне второй NSFetchedResultsController, который извлекает только совпадающие элементы, или я могу использовать тот же, что и основной TableView?
Если я использую тот же самый, это так же просто, как очистить кэш FRC и затем изменить предикат в методе handleSearchForTerm: searchString? Должен ли предикат содержать исходный предикат, а также условия поиска, или он помнит, что он использовал предикат для извлечения данных в первую очередь?
Как мне вернуться к исходным результатам? Должен ли я установить предикат поиска равным нулю? Разве это не убьет исходный предикат, который использовался для получения результатов FRC?
Если у кого-нибудь есть примеры кода с использованием поиска в FRC, я был бы очень признателен!
Ответы:
Я на самом деле только что реализовал это в одном из моих проектов (ваш вопрос и другой неправильный ответ подсказали, что делать). Я попробовал ответить Серхио, но у меня возникли проблемы с исключениями при работе на устройстве.
Да, вы создаете два контроллера результатов выборки: один для обычного отображения и другой для табличного представления UISearchBar.
Если вы используете только один FRC (NSFetchedResultsController), то исходный UITableView (а не табличное представление поиска, которое активно во время поиска) может вызвать обратные вызовы во время поиска и попытаться неправильно использовать отфильтрованную версию вашего FRC, и вы увидите исключения выброшено о неправильном количестве разделов или строк в разделах.
Вот что я сделал: у меня есть два FRC, доступные как свойства fetchedResultsController и searchFetchedResultsController. SearchFetchedResultsController не должен использоваться, если нет поиска (когда поиск отменен, вы можете увидеть ниже, что этот объект освобожден). Все методы UITableView должны выяснить, из какого табличного представления он будет запрашивать и из какого применимого FRC извлекать информацию. Методы делегата FRC также должны выяснить, какой tableView следует обновить.
Удивительно, насколько это стандартный код.
Соответствующие биты заголовочного файла:
соответствующие биты файла реализации:
Я создал полезный метод для получения правильного FRC при работе со всеми методами UITableViewDelegate / DataSource:
Методы делегирования для панели поиска:
убедитесь, что вы используете правильное табличное представление при получении обновлений от методов делегата FRC:
Другая информация для просмотра:
Код создания FRC:
источник
searchFetchedResultsController
наnil
каждый раз , когда изменения текста поиска.cellForRowAtIndexPath
, разве вы не должны получить клетку,self.tableView
как кто-то указал в этом вопросе? Если вы этого не сделаете, пользовательская ячейка не отображается.Некоторые отметили, что это можно сделать с помощью одного
NSFetchedResultsController
. Это то, что я сделал, и вот подробности. Это решение предполагает, что вы просто хотите отфильтровать таблицу и сохранить все другие аспекты (порядок сортировки, расположение ячеек и т. Д.) Результатов поиска.Сначала определите два свойства в вашем
UITableViewController
подклассе (с соответствующими @synthesize и dealloc, если применимо):Во-вторых, инициализируйте строку поиска в
viewDidLoad:
методе вашегоUITableViewController
подкласса:В-третьих, реализуйте
UISearchDisplayController
методы делегата следующим образом:Наконец, в
fetchedResultsController
методе изменитеNSPredicate
зависимость, еслиself.searchString
определено:источник
Мне понадобилось несколько попыток, чтобы заставить это работать ...
Моим ключом к пониманию было понимание того, что здесь работают два tableView. Один управляется моим viewcontroller, а другой - searchviewcontroller, а затем я могу проверить, какой из них активен, и делать правильные вещи. Документация тоже была полезна:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UISearchDisplayController_Class/Reference/Reference.html
Вот что я сделал -
Добавлен флаг searchIsActive:
Добавлен синтез в файле реализации.
Затем я добавил эти методы для поиска:
Затем в controllerWillChangeContent:
И controllerDidChangeContent:
И удалите кеш при сбросе предиката.
Надеюсь это поможет.
источник
if ( [self.tableView isEqual:self.searchDisplayController.searchResultsTableView] ) { ... }
Я столкнулся с той же задачей и нашел самый простой способ ее решить. Коротко: вам нужно определить еще один метод, очень похожий на
-fetchedResultsController
пользовательский составной предикат.В моем личном случае мой
-fetchedResultsController
выглядит так:Как видите, я выбираю клиентов одного агентства, отфильтрованных по
agency.server_id
предикату. В результате я получаю свой контент вtableView
(все, что связано с реализациейtableView
иfetchedResultsController
кодом довольно стандартно). Для реализацииsearchField
я определяюUISearchBarDelegate
метод делегата. Я запускаю его методом поиска, скажем-reloadTableView
:и конечно определение
-reloadTableView
:Этот набор кода очень похож на первый, «стандартный»
-fetchedResultsController
НО внутри оператора if-else:+andPredicateWithSubpredicates:
- используя этот метод, мы можем установить предикат для сохранения результатов нашей основной первой выборки вtableView
+orPredicateWithSubpredicates
- используя этот метод, мы фильтруем существующую выборку по поисковому запросу изsearchBar
В конце я устанавливаю массив предикатов как составной предикат для этой конкретной выборки. И для обязательных предикатов, ИЛИ для необязательных.
И это все! Вам не нужно ничего больше реализовывать. Удачного кодирования!
источник
Вы используете живой поиск?
Если вы НЕ, возможно, вы хотите массив (или NSFetchedResultsController) с предыдущими поисками, которые вы использовали, когда пользователь нажимает «поиск», вы говорите своим FetchedResults изменить его предикат.
В любом случае вам нужно будет каждый раз перестраивать свои FetchedResults. Я рекомендую использовать только один NSFetchedResultsController, так как вам придется многократно дублировать код, и вам не нужно тратить память на то, что вы не показываете.
Просто убедитесь, что у вас есть переменная NSString "searchParameters", и ваш метод FetchedResults перестраивает ее для вас по мере необходимости, используя параметры поиска, если они доступны, вы должны просто сделать:
Вот простой код:
источник
Swift 3.0, UISearchController, NSFetchedResultsController и Core Data
Этот код будет работать на Swift 3.0 с
Core Data
! Вам понадобится один метод делегата и несколько строк кода для фильтрации и поиска объектов из модели. Ничего не понадобится, если вы реализовали всеFRC
и ихdelegate
методы, а такжеsearchController
.Метод
UISearchResultsUpdating
протоколаЭто оно! Надеюсь, это поможет вам! Спасибо
источник
SWIFT 3.0
Использование textField, UISearchDisplayController устарела, начиная с iOS 8, вам придется использовать UISearchController. Вместо того чтобы иметь дело с контроллером поиска, почему бы вам не создать свой собственный механизм поиска? Вы можете настроить его больше и иметь больше контроля над ним, и вам не нужно беспокоиться об изменении SearchController и / или об его устаревании.
Этот метод, который я использую, работает очень хорошо и не требует большого количества кода. Однако для этого необходимо использовать Core Data и реализовать NSFetchedResultsController.
Сначала создайте TextField и зарегистрируйте его с помощью метода:
Затем создайте свой метод textFieldDidChange, описанный в селекторе при добавлении цели:
Затем вы хотите отфильтровать список в
filterList()
методе, используя предикат NSPredicate или NSCompound, если он более сложный. В моем методе filterList я выполняю фильтрацию на основе имени объекта и имени объекта "subCategories" (отношение один ко многим).источник
Я думаю, что Лука лучше подходит для этого. Смотрите LargeDataSetSample и его причину
Он не использует
FetchedResultsController
, но использует кеш при поиске, поэтому результаты поиска появляются намного быстрее, когда пользователь вводит больше в SearchBarЯ использовал его подход в своем приложении, и он работает хорошо. Также помните, если вы хотите работать с объектом Model, сделайте его как можно более простым, см. Мой ответ о setPropertiesToFetch
источник
Вот способ обработки fetchedResults с несколькими наборами данных, который является простым и достаточно общим для применения практически в любом месте. Просто захватите ваши основные результаты в массив, когда какое-то условие присутствует.
Сделайте запрос к массиву, просматривая его или все, что вы хотите, чтобы создать подмножество ваших основных fetchedResults. И теперь вы можете использовать полный набор или подмножество, когда присутствует какое-либо условие.
источник
Мне очень понравился подход @Josh O'Connor, когда он не использует
UISearchController
. Этот контроллер все еще (Xcode 9) имеет ошибку компоновки, которую многие пытаются обойти.Я вернулся к использованию
UISearchBar
вместоUITextField
, и это работает довольно хорошо. Мое требование для поиска / фильтра заключается в созданииNSPredicate
. Это передается в FRC:...
Наконец, подключите SearchBar к его делегату.
Я надеюсь, что это помогает другим
источник
Простой подход для фильтрации существующего UITableView с использованием CoreData и который уже отсортирован, как вы хотите.
Это буквально слишком 5 минут, чтобы настроить и начать работать.
У меня было существующее
UITableView
использование,CoreData
заполненное данными из iCloud, которое имеет довольно сложные взаимодействия с пользователем, и я не хотел повторять все это для aUISearchViewController
. Мне удалось просто добавить предикат к существующему, которыйFetchRequest
уже используетсяFetchResultsController
и который фильтрует уже отсортированные данные.источник