Динамическая фильтрация с Swift CoreData - PullRequest
0 голосов
/ 02 октября 2018

Я занимаюсь разработкой приложения, которое извлекает данные из CoreData.Я получаю список элементов из базы данных и отображаю их на экране.

У пользователя есть возможность отфильтровать эти элементы по 5 категориям в 5 отдельных выпадающих списках.Каков наилучший способ сделать это динамически?Под этим я подразумеваю, что если пользователь выбирает один параметр фильтра, будут отображаться только элементы, соответствующие этому фильтру, а также другие параметры фильтра, а затем только те параметры фильтра, которые существуют для уже отфильтрованных элементов.

Надеюсь, это имеет смысл!

Это код, который у меня есть для получения предметов:

func showDropDown(filterButton: UIButton) -> Void {
        selectedButton = filterButton
        let popController = UIStoryboard(name: STORYBOARD_NAME,
                                         bundle: nil).instantiateViewController(withIdentifier: STORYBOARD_ID) as! FilterDropDownViewController

        popController.modalPresentationStyle = .popover
        popController.delegate = self
        popController.popoverPresentationController?.permittedArrowDirections = .up
        popController.popoverPresentationController?.delegate = self
        popController.popoverPresentationController?.sourceView = filterButton
        popController.popoverPresentationController?.sourceRect = filterButton.bounds

        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let context = appDelegate.persistentContainer.viewContext

        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Item")
        var predicate = NSPredicate(format: "code matches[c] '\(code!)'")
        fetchRequest.returnsObjectsAsFaults = false
        fetchRequest.predicate = predicate
        let entity = NSEntityDescription.entity(forEntityName: "Item",
                                                in: context)

        fetchRequest.resultType = .dictionaryResultType
        let entityProperties = entity?.propertiesByName
        let filterToFetch = "filter\(filterButton.tag)"
        let propertiesToFetch: [Any] = [entityProperties![filterToFetch]!]
        fetchRequest.propertiesToFetch = propertiesToFetch
        fetchRequest.returnsDistinctResults = true

        var result = [[String : String]]()

        do {
            result = try context.fetch(fetchRequest) as! [[String : String]]
        } catch {
            print("Unable to fetch managed objects for Item).")
        }

        var filterArray = [Filter]()
        for dict in result {
            if let search = dict[filterToFetch] {
                predicate = NSPredicate(format: "code matches[c] '\(search)'")
                let filterCode = DatabaseHelper.fetchRecordsForEntity(entity: "Filter",
                                                                      managedObjectContext: context,
                                                                      predicate: predicate) as! [Filter]

                filterArray.append(filterCode.first!)
            }
        }

        popController.filterArray = filterArray

        present(popController, animated: true, completion: nil)
}

1 Ответ

0 голосов
/ 04 октября 2018

Вы можете сделать это с помощью следующих простых шагов:

  1. Создать NSFetchResultsController с соответствующим предикатом на основе текущих настроек фильтра (используйте NSCompoundPredicate) и извлечь его.Установите контроллер представления в качестве делегата и перезагрузите данные collectionView при изменении данных (кажется, что вы не ожидаете, что данные изменятся, пока пользователь просматривает его, поэтому вы можете просто сохранить его простым).Не забудьте перезагрузить collectionView при обновлении NSFetchResultsController.
  2. Теперь выполните все fetchedObjects в NSFetchResultsController и посмотрите, какие фильтруемые свойства у него есть.Добавьте эти свойства в набор (по одному для каждой категории фильтров).Затем посмотрите на набор, чтобы определить, какие фильтры следует отображать, и обновите пользовательский интерфейс.
  3. При изменении фильтра установите делегат текущего NSFetchResultsController на ноль, прежде чем создавать новый, и создавать новый какописано в первом шаге.

В коде, которым вы поделились, вы без необходимости выполняете сложную выборку, чтобы выяснить, какие фильтры актуальны.Я не знаю, правильный ли ваш код или нет, но я знаю, что это сложно.И быстрее взглянуть на свойства в управляемом объекте, к которым у вас уже есть доступ в fetchResultsController.Эти элементы уже извлечены и находятся в памяти - поэтому нет необходимости снова попадать в базу данных.А отфильтровать эти элементы в коде проще, чем понять, как написать сложный предикат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...