简体   繁体   English

根据过滤器数组过滤UICollectionView

[英]Filtering UICollectionView depending on filter array

I am having a problem that I can't find a good answer to by myself. 我遇到一个我自己找不到好的答案的问题。

I have an array containing objects that contain information about companies. 我有一个包含对象的数组,这些对象包含有关公司的信息。 Based on this objects I create a collection view where I populate the items from the information inside those objects. 基于此对象,我创建一个集合视图,在其中从这些对象内部的信息中填充项目。

var suppliers = [Suppliers]()

Now I want to add buttons with specific filters. 现在,我想添加带有特定过滤器的按钮。 When pressed on one or more of those buttons the collection view should update with the filters applied. 当按下其中一个或多个按钮时,收集视图应使用已应用的过滤器进行更新。

Therefore I made a few buttons and when pressed I add them to an array containing all the filters. 因此,我做了几个按钮,当我按下按钮时,将它们添加到包含所有过滤器的数组中。

var filters = [Category]()

After that I call a method that should do the filtering and update the collection view. 之后,我调用一个应该进行过滤并更新集合视图的方法。

private func filter()
{
    if filters.count > 0 {
        suppliers.filter({ ($0.category!).contains(filters)})
    }
}

Unfortunately I can't comparison like that, according to xCode. 不幸的是,根据xCode,我无法像那样进行比较。 How do I achieve this filtering correctly? 如何正确实现此过滤?

edit: See the structure of the object below. 编辑:请参见下面的对象结构。

struct Supplier : JSONJoy {

    var about: String?
    var category: Array<Category>?
    var logo: String?
    var name: String?

    init(_ decoder: JSONDecoder) {
        name = decoder["name"].string
        logo = decoder["logo"].string
        about = decoder["about"].string
        if let ctgrys = decoder["category"].array {
            category = Array<Category>()
            for ctgryDecoder in ctgrys {
                category?.append(Category(ctgryDecoder))
            }
        }
}

struct Category : JSONJoy {
    var id: Int?
    var name: String?

    init(_ decoder: JSONDecoder) {
        id = decoder["id"].integer
        name = decoder["name"].string
    }

}

1) $0.category! 1) $0.category! is [Category] type. [Category]类型。 And you have [Category].contains call which requires (Category) throws -> Bool parameter, but in your case it is filters variable with [Category] type 并且您有[Category].contains调用,它要求(Category) throws -> Bool参数,但是在您的情况下,它是[Category]类型的filters变量

2) You never apply your filter result 2)您永远不会套用筛选结果

This is possible implementation of your filtering, if I understand your needs correctly: 如果我正确理解了您的需求,则可以执行您的过滤:

private func filter() -> [Supplier] {
    if filters.count > 0 {
        return suppliers.filter { supplier in
            return supplier.category?.contains { supplierCategory in
                return filters.contains {
                    return supplierCategory.id == $0.id
                }
            } ?? false
        }
    } else {
        return suppliers
    }
}

We need to fix a couple of details that are going to make our lifes easier :) 我们需要修复一些细节,这将使我们的生活更轻松:)

1. Category becomes Equatable and Hashable 1.类别变得平等和可哈希

struct Category: JSONJoy, Equatable, Hashable {
    var id: Int?
    var name: String?

    init(_ decoder: JSONDecoder) {
        id = decoder["id"].integer
        name = decoder["name"].string
    }
    var hashValue: Int { get { return id?.hashValue ?? 0 } }
}

func ==(left:Category, right:Category) -> Bool {
    return left.id == right.id && left.name == right.name
}

2. Supplier does not like an optional category property 2.供应商不喜欢可选的类别属性

struct Supplier: JSONJoy {

    var about: String?
    var category = [Category]() // <- I changed this
    var logo: String?
    var name: String?

    init(_ decoder: JSONDecoder) {
        name = decoder["name"].string
        logo = decoder["logo"].string
        about = decoder["about"].string
        if let ctgrys = decoder["category"].array {
            category = Array<Category>()
            for ctgryDecoder in ctgrys {
                category.append(Category(ctgryDecoder))
            }
        }
    }
}

3. Now let't filter them all 3.现在,不要全部过滤

You have your list of suppliers and your list of filters 您有供应商清单和过滤器清单

var suppliers = [Supplier]()
var filters = [Category]()

Now I am not sure about how you want to filter suppliers . 现在我不确定如何过滤suppliers

However IF you want all the suppliers having at least a filter listed in filters then 但是, 如果您希望所有供应商在filters 中至少列出一个过滤 filters

let requiredFilters = Set(filters)
let supplierWithAtLeastOneRequiredFilter = suppliers.filter { !Set($0.category).intersect(requiredFilters).isEmpty }

On the other hand IF you want all the suppliers having all the filters listed in filters then 另一方面, 如果您希望所有供应商的过滤器中列出所有过滤 filters

let requiredFilters = Set(filters)
let supplierWithEveryRequiredFilter = suppliers.filter { Set($0.category).isSupersetOf(filters) }

Assuming filtered is the filtered array of Supplier . 假设已filteredSupplier的已过滤array and AllData is the full array of Supplier . AllDataSupplier的完整数组。 And you want to filter only items which contain the word "ao" at their name property. 而且,您只想过滤name属性中包含单词"ao"项目。

  filtered  = AllData.filter {
                $0.name.rangeOfString("ao", options: .CaseInsensitiveSearch) != nil
            }
        if(filtered.count == 0){
           //No Results - 
        } else {
              //There are results - update the tableView data source accordingly
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM