API Reference / iOS InstantSearch Widgets / Current Refinements
Apr. 24, 2019

Current Refinements

About this widget #

Current Refinements shows the currently active refinements within a given FilterState and lets users remove filters individually.

To add current refinements to your search experience, use these components:

  • CurrentFiltersInteractor: The logic for current refinements in the FilterState.
  • FilterState: The current state of the filters.
  • CurrentFiltersController: The controller that interfaces with a concrete current refinement view.
  • Presenter: Optional. The presenter that defines the way we want to display a filter.

Examples #

1
2
3
4
5
6
7
8
9
10
11
let currentFiltersInteractor: CurrentFiltersInteractor = .init()
let currentFiltersController: CurrentFilterListTableController = .init(tableView: UITableView())
let filterState: FilterState = .init()

override func viewDidLoad() {
  super.viewDidLoad()

  currentFiltersInteractor.connectFilterState(filterState)
  currentFiltersInteractor.connectController(currentFiltersController)
}

Parameters #

filterGroupID #
type: FilterGroup.ID?
default: nil
Optional

When specified, only display current refinements matching this FilterGroupID.

Edit
1
2
3
4
let colorGroup = FilterGroup.ID.and(name: "color")

currentFiltersInteractor.connectFilterState(
  filterState, filterGroupID: colorGroup)

Presenter #

Filter Presenter #
type: (Filter) -> String
Optional

The presenter that defines the way we want to display a filter.

Edit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    currentFiltersInteractor.connectController(currentFiltersController, customPresenter)

    let customPresenter: (Filter) -> String = { filter in
      let attributeName = filter.filter.attribute.name

      switch filter {
      case .facet(let facetFilter):
        switch facetFilter.value {
        case .bool:
          return filter.filter.attribute.name

        case .float(let floatValue):
          return "\(attributeName): \(floatValue)"

        case .string(let stringValue):
          return stringValue
        }

      case .numeric(let numericFilter):

        switch numericFilter.value {
        case .comparison(let comp):
          return "\(attributeName) \(comp.0) \(comp.1)"

        case .range(let range):
          return "\(attributeName): \(range.lowerBound) to \(range.upperBound)"
        }

      case .tag(let tagFilter):
        return tagFilter.value
      }
    }

Customize your view#

The controllers provided by default, like the CurrentFilterListTableController work well when you want to use native UIKit with their default behavior.

If you want to use another component (other than a UITableView) such as a UICollectionView, a third-party input view, or you want to introduce some custom behavior to the already provided UIKit component, you can create your own controller conforming to the CurrentFiltersController protocol.

Protocol#

func setItems(_ item: [FilterAndID]):

Function called when current filters are refreshed and need to be updated.

Note that FilterAndID is a struct that contains the filter, its ID, and the text representation of the filter

var onRemoveItem: ((FilterAndID) -> Void)?:

Closure to call when a “remove filter” intention is detected on the corresponding current filter.

func reload():

Function called when the view needs to reload itself with new data.

Example#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
open class CurrentFilterListTableController: NSObject, CurrentFiltersController, UITableViewDataSource, UITableViewDelegate {

  open var onRemoveItem: ((FilterAndID) -> Void)?

  public let tableView: UITableView

  public var items: [FilterAndID] = []

  private let cellIdentifier = "CurrentFilterListTableControllerCellID"

  public init(tableView: UITableView) {
    self.tableView = tableView
    super.init()
    tableView.dataSource = self
    tableView.delegate = self
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellIdentifier)
  }

  open func setItems(_ item: [FilterAndID]) {
    items = item
  }

  open func reload() {
    tableView.reloadData()
  }

  // MARK: - UITableViewDataSource

  open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return items.count
  }

  open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
    let filterAndID = items[indexPath.row]
    cell.textLabel?.text = filterAndID.text

    return cell
  }

  // MARK: - UITableViewDelegate

  open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    onRemoveItem?(items[indexPath.row])
  }

}

Did you find this page helpful?