Filter List (Tag)
TagFilterListConnector( tagFilters: [TagFilter], selectionMode: SelectionMode, filterState: FilterState, operator: RefinementOperator, groupName: String, controller: FilterListTableController<Filter.Tag> )
About this widget
TagFilterList is a filtering component that displays tag filters and lets the user refine the search results by selecting them.
Compared to the RefinementList, which takes its values from the search response facets, this widget displays tag filters that you add yourself.
Examples
Instantiate a TagFilterListConnector and launch an initial search on its Searcher.
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
let searcher = HitsSearcher(appID: "YourApplicationID",
                            apiKey: "YourSearchOnlyAPIKey",
                            indexName: "YourIndexName")
let filterState = FilterState()
let filters: [Filter.Tag] = [
  "coupon",
  "free shipping",
  "free return",
  "on sale",
  "no exchange"
]
let filterListTableView: UITableView = .init()
let filterListController: FilterListTableController<Filter.Tag> = .init(tableView: filterListTableView)
let filterListConnector = TagFilterListConnector(tagFilters: filters,
                                                 selectionMode: .multiple,
                                                 filterState: filterState,
                                                 operator: .and,
                                                 groupName: "Tag Filters",
                                                 controller: filterListController)
searcher.connectFilterState(filterState)
searcher.search()
Parameters
| Parameter | Description | 
|---|---|
          
            tagFilters
          
         | 
        
           
                
                type: [TagFilter]
                
               
              
                
                  default: []
                
               
              
                
                        Required
                
               
          The tag filters to display.  | 
      
          
            selectionMode
          
         | 
        
           
                
                type: SelectionMode
                
               
              
                
                  default: .multiple
                
               
              
                
                    Optional
                
               
          Whether a user can select   | 
      
          
            filterState
          
         | 
        
           
                
                type: FilterState
                
               
              
                
                        Required
                
               
          The   | 
      
          
            operator
          
         | 
        
           
                
                type: RefinementOperator
                
               
              
                
                        Required
                
               
          Whether we apply an  For example if we have an   | 
      
          
            groupName
          
         | 
        
           
                
                type: String
                
               
              
                
                        Required
                
               
          Filter group name.  | 
      
          
            controller
          
         | 
        
           
                
                type: FilterListTableController<Filter.Tag>
                
               
              
                
                  default: nil
                
               
              
                
                    Optional
                
               
          Controller interfacing with a concrete filter list view.  | 
      
Low-level API
If you want to fully control the TagFilterList components and connect them manually, you can use the following components:
Searcher: TheSearcherthat handles your searches.FilterState: The current state of the filters.TagFilterListInteractor: The logic applied to the tag filters.FilterListController: The view that will render the tag filters.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
let searcher = HitsSearcher(appID: "YourApplicationID",
                            apiKey: "YourSearchOnlyAPIKey",
                            indexName: "YourIndexName")
let filterState = FilterState()
let filters: [Filter.Tag] = [
  "coupon",
  "free shipping",
  "free return",
  "on sale",
  "no exchange"
]
let filterListTableView: UITableView = .init()
let filterListController: FilterListTableController<Filter.Tag> = .init(tableView: filterListTableView)
let filterListInteractor = TagFilterListInteractor(items: filters,
                                                  selectionMode: .multiple)
filterListInteractor.connectFilterState(filterState, operator: .and, groupName: "Tag Filters")
filterListInteractor.connectController(filterListController)
searcher.connectFilterState(filterState)
searcher.search()
Customizing your view
The default controllers, e.g., the FilterListTableController work well when you want to use native UIKit with their default behavior.
If you want to use another component 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 TagFilterListController protocol.
Protocol
var onClick: ((Filter.Tag) -> Void)?:
Closure to call when a filter is clicked.
func setSelectableItems(selectableItems: [SelectableItem<Filter.Tag>])
Function called when a new array of selectable facets is updated. This is the UI State of the refinement list.
func reload()
Function called when we require a reload of the list view.
Implementation 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
48
49
50
51
52
53
54
class TagFilterListTableController: NSObject, TagFilterListController, UITableViewDataSource, UITableViewDelegate {
  
  public var onClick: ((Filter.Tag) -> Void)?
  
  public let tableView: UITableView
  
  public var selectableItems: [SelectableItem<Filter.Tag>] = []
  public var filterPresenter: FilterPresenter?
  
  let cellID: String
  
  public init(tableView: UITableView, cellID: String = "cellID") {
    self.tableView = tableView
    self.cellID = cellID
    super.init()
    tableView.dataSource = self
    tableView.delegate = self
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellID)
  }
  
  // MARK: - FilterListController
  
  public func setSelectableItems(selectableItems: [SelectableItem<Filter.Tag>]) {
    self.selectableItems = selectableItems
  }
  
  public func reload() {
    tableView.reloadData()
  }
  
  // MARK: - UITableViewDataSource
  
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return selectableItems.count
  }
  
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath)
    let filter = selectableItems[indexPath.row]
    let filterPresenter = self.filterPresenter ?? DefaultPresenter.Filter.present
    cell.textLabel?.text = filterPresenter(Filter(filter.item))
    cell.accessoryType = filter.isSelected ? .checkmark : .none
    
    return cell
  }
  
  // MARK: - UITableViewDelegate
  
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let selectableItem = selectableItems[indexPath.row]
    onClick?(selectableItem.item)
  }
  
}
SwiftUI
InstantSearch provides the FilterList SwiftUI view which you can embed in your views.
It uses FilterListObservableController as a data model, which is an implementation of the SelectableListController protocol adapted for usage with SwiftUI.
FilterListObservableController must be connected to the TagFilterListConnector or TagFilterListInteractor like any other SelectableListController implementation.
You have to define the appearance of the view representing a single tag filter and its selection state.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct ContentView: View {
  @ObservedObject var filterListController: FilterListObservableController<Filter.Tag>
  var body: some View {
    FilterList(filterListController) { filter, isSelected in
      // declare the view presenting a single tag filter and its selection state
      HStack {
        Text(filter.value.description)
        Spacer()
        if isSelected {
          Image(systemName: "checkmark")
            .foregroundColor(.accentColor)
        }
      }
      .contentShape(Rectangle())
      .frame(idealHeight: 44)
      .padding(.horizontal, 5)
    }
  }
}
If you prefer to create a custom SwiftUI view that presents the list of tag filters, you can directly use the FilterListObservableController<Filter.Tag> as a data model.
It provides filters and selections properties along with toggle and isSelected functions to streamline the design process of your custom SwiftUI view.