RelevantSort
# <!-- vale off --> # The actual component name is `interactor`, so the linting rule is ignored here RelevantSortConnector<Controller: RelevantSortController, Output>( searcher: SingleIndexSearcher, interactor: RelevantSortInteractor, controller: Controller, presenter: RelevantSortPresenter<Output> ) RelevantSortConnector<Controller: RelevantSortController, Output>( searcher: SingleIndexSearcher, interactor: RelevantSortInteractor, controller: Controller, presenter: RelevantSortTextualPresenter ) # <!-- vale on -->
About this widget
Virtual indices allow you to use Relevant sort, a sorting mechanism that favors relevancy over the attribute you’re sorting on. The relevantSort
widget displays the current search mode when searching in a virtual replica index, and allows users to switch between relevant and regular sorting, which is more exhaustive and can return less relevant results.
Examples
Instantiate a RelevantSortConnector
.
1
2
3
4
5
let searcher = HitsSearcher(appID: "YourApplicationID",
apiKey: "YourSearchOnlyAPIKey",
indexName: "virtual_replica_index")
let relevantSortController: ButtonRelevantSortController = .init()
let relevantSortConnector: RelevantSortConnector = .init(searcher: searcher, controller: relevantSortController)
Parameters
searcher
|
type: HitsSearcher
Required
The |
interactor
|
type: RelevantSortInteractor
default: .init()
Required
The logic to toggle Relevant Sort. |
controller
|
type: RelevantSortController
default: nil
Optional
Controller that presents and can toggle the Relevant Sort priority state. |
presenter
|
type: RelevantSortPresenter<Output> | RelevantSortTextualPresenter
default: DefaultPresenter.RelevantSort.present
Required
Presenter transforming the Relevant sort priority state to its representation for a controller. |
Presenter
RelevantSort Presenter
|
type: RelevantSortPresenter<Output> | RelevantSortTextualPresenter
default: DefaultPresenter.RelevantSort.present
Required
Presenter transforming the Relevant sort priority state to its representation for a controller. Default presenter transforms Relevant sort priority to ‘RelevantSortTextualRepresentation?’ providing a tuple of string constants in english. |
||
Copy
|
Low-level API
If you want to fully control the RelevantSort
components and connect them manually, you can use the following components:
Searcher
: TheSearcher
that handles your searches.RelevantSortInteractor
: Relevant sort priority toggling logic.RelevantSortController
: the controller that presents and toggles the Relevant sort priority state.RelevantSortPresenter<Output>
: optional. Generic presenter transforming the Relevant Sort priority state to its representation for a controller.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let searcher = HitsSearcher(appID: "YourApplicationID",
apiKey: "YourSearchOnlyAPIKey",
indexName: "virtual_replica_index")
let relevantSortInteractor = RelevantSortInteractor()
let relevantSortController: ButtonRelevantSortController = .init()
relevantSortInteractor.connectSearcher(searcher)
let relevantSortpresenter: RelevantSortTextualPresenter = { priority in
switch priority {
case .some(.hitsCount):
return ("Currently showing all results.", "Show more relevant results")
case .some(.relevancy):
return ("We removed some search results to show you the most relevants ones.", "Show all results")
default:
return nil
}
}
relevantSortInteractor.connectController(relevantSortController, presenter: relevantSortpresenter)
Customizing your view
The controllers provided by default, like the ButtonRelevantSortController
work well when you want to use native UIKit with their default behavior like a UIButton
.
If you want to use another component, 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 RelevantSortController
protocol.
Protocol
func setItem(_ item: RelevantSortTextualRepresentation?)
Function called when a new array of indices is defined.
var didToggle: (() -> Void)? { get set }
Closure triggered by the controller when the toggle happens (for example, toggle button clicked or switch control state changed)
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
public class RelevantSortControl: NSObject, RelevantSortController {
public let hintLabel: UILabel
public let toggleButton: UIButton
public var didToggle: (() -> Void)?
public init() {
hintLabel = .init()
toggleButton = .init()
super.init()
toggleButton.addTarget(self, action: #selector(didTapToggleButton), for: .touchUpInside)
}
public func setItem(_ item: RelevantSortTextualRepresentation?) {
hintLabel.isHidden = item == nil
toggleButton.isHidden = item == nil
hintLabel.text = item?.hintText
toggleButton.setTitle(item?.toggleTitle, for: .normal)
}
@objc func didTapToggleButton() {
didToggle?()
}
}
SwiftUI
InstantSearch provides the RelevantSortObservableController
data model, which is an implementation of the RelevantSortController
protocol adapted for usage with SwiftUI.
RelevantSortObservableController
must be connected to the RelevantSortConnector
or RelevantSortInteractor
like any other RelevantSortController
implementation.
The example of the SwiftUI view presenting the relevant sort state.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct ContentView: View {
@ObservedObject var relevantSortController: RelevantSortObservableController
var body: some View {
VStack {
if let state = relevantSortController.state {
HStack {
Text(state.hintText)
Spacer()
Button(state.toggleTitle,
action: relevantSortController.toggle)
}
}
}
}
}
If you prefer to create a custom SwiftUI view that presents the list of facets, you can directly use the RelevantSortObservableController
as a data model.
It provides the state
property along with the toggle
function to streamline the design process of your custom SwiftUI view.
Check out the example to see this widget in action.