Как совместить поиск и фильтрацию разными методами? - PullRequest
0 голосов
/ 03 августа 2020

У меня есть viewController, отображающий продукты в данной группе продуктов, и в этом V C у меня есть как searchBar, так и специальное решение для фильтрации, и я изо всех сил пытаюсь найти лучший подход, чтобы они оба работали безразлично. рядом.

enter image description here

I've only implemented inStock for now, and it works, but I want the filters and the searchBar to work on top of each other.

Example data:

let products = [Product]() {
return [ 
Product(name: "Apple", stock: 5),
Product(name: "AppleJuice", stock: 5),
Product(name: "Orange", stock: 0),
Product(name: "baskedOfApples", stock: 0) ]

Как это работает сейчас:

При поиске Apple отображается индекс 0,1,3 -> Добавление фильтр «В наличии» удаляет индекс 3. -> удаление фильтра ничего не делает, так как последний показанный массив является результатом нескольких копий из-за фильтра

Предложение:

Поскольку поиск / фильтрация выполняется на основе различных методов-делегатов, является ли допустимый подход иметь базовый массив со всеми продуктами, затем создать filterProducts [] и searchchedProducts [], а затем иметь окончательный displayProducts [], который все элементы, присутствующие в обоих массивах? Меня беспокоит, что l oop будет сложно сравнивать эти два для каждого обновления поиска / фильтра?

Текущий код:

    // MARK: - Properties
    
    var productsInSelectedCategoryGroup = [Product]()
    private var searchedProducts = [Product]()
    private var filteredProducts = [Product]()
    private var searchController = FUISearchController(searchResultsController: nil)
    private var filterFeedbackControl: FUIFilterFeedbackControl!
    private var categoryGroup = FUIFilterGroup()
    
    private var displayedProducts: [Product] {
        if isSearching() {
            return searchedProducts
        } else if !filterFeedbackControl.filterItems.filter({ $0.isActive }).isEmpty {
            return filteredProducts
        } else {
            return productsInSelectedCategoryGroup
        }
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return displayedProducts.count
    }

    func isSearching() -> Bool {
        return searchController.isActive && !searchTextIsEmpty()
    }

    func searchProducts(_ searchText: String) {
        
        let productsToSearch = !filterFeedbackControl.filterItems.filter({ $0.isActive }).isEmpty ? filteredProducts : productsInSelectedCategoryGroup

        searchedProducts = productsToSearch.filter( {(product : Product) -> Bool in
            return product.title.lowercased().contains(searchText.lowercased())
        })
        tableView.reloadData()
    }
extension ProductsViewController: FUIFilterResultsUpdating {
    
    func updateFilterResults(for filterFeedbackControl: FUIFilterFeedbackControl) {
        
        let productsToFilter = isSearching() ? searchedProducts : productsInSelectedCategoryGroup
        filteredProducts.removeAll()
        let activeFilterItems = filterFeedbackControl.filterItems.filter({ $0.isActive })
        if !activeFilterItems.isEmpty {
            
            for filterItem in categoryGroup.items {
                if activeFilterItems.contains(filterItem) {
                    let _filteredProducts = productsToFilter.filter {(product: Product) in
                        
                        switch filterItem.key {
                        case AccessibilityIdentifier.inStockFilterFeedbackKey.rawValue:
                            return product.storeStock > 1
                        default:
                            return false
                        }
                    }
                    filteredProducts.append(contentsOf: _filteredProducts)
                }
            }
        } else {
            filteredProducts = productsToFilter
        }
        tableView.reloadData()
    }
}

1 Ответ

1 голос
/ 03 августа 2020

Вы можете создавать разные функции фильтрации для каждого критерия поиска / фильтрации, а затем применять их с помощью массива и filter

typealias ProductFilter = (Product) -> Bool
var searchKey: String! //just for this example
var newDate: Date! //just for this example, not sure what New filter means

let nameFilter: ProductFilter = { $0.name.lowercased().contains(searchKey) }
let stockFilter: ProductFilter = { $0.stock > 0 }
let discontinuedFilter: ProductFilter = { $0.discontinued }
let newFilter: ProductFilter = {$0.date > newDate}

, а затем применять фильтр с помощью ключа поиска

let filterArray = [nameFilter, stockFilter]

searchKey = "app"
let filtered = products.filter { product in
    filterArray.first(where: {!$0(product)}) == nil
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...