Sort By
SortByConnector( searcher: AnyObject & Searchable & IndexNameSettable, indicesNames: [IndexName], selected: Selected?, controller: SelectableSegmentController )
About this widget
SortBy
displays a list of indices, allowing a user to change the way hits are sorted (using replica indices). Another common use case is to let the user switch between different indices to show different results.
For this to work, you must define all indices that you pass to SortBy
as replicas of the main index.
Examples
Instantiate a SortByConnector
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let searcher: HitsSearcher = .init(appID: "YourApplicationID",
apiKey: "YourSearchOnlyAPIKey",
indexName: "indexDefault")
let alertController = UIAlertController(title: "Change Index",
message: "Please select a new index",
preferredStyle: .actionSheet)
let selectIndexController: SelectIndexController = .init(alertController: alertController)
let sortByConnector: SortByConnector = .init(searcher: searcher,
indicesNames: ["indexDefault",
"indexAscendingOrder",
"indexDescendingOrder"],
selected: 0,
controller: selectIndexController) { indexName -> String in
switch indexName {
case "indexDefault": return "Default"
case "indexAscendingOrder": return "Year Asc"
case "indexDescendingOrder": return "Year Desc"
default: return indexName.rawValue
}
}
Parameters
searcher
|
type: AnyObject & Searchable & IndexNameSettable
Required
The |
interactor
|
type: SortByInteractor
default: .init()
Required
The logic applied to SortBy. |
indicesNames
|
type: [IndexName]
Required
The list of indices names to search in. |
selected
|
type: Int?
Optional
The consecutive index of the initially selected search index in the list. |
controller
|
type: SelectableSegmentController
default: nil
Optional
Controller interfacing with a concrete sortBy view. |
presenter
|
type: Presenter
default: nil
Optional
The presenter defining how index names appear in the controller. |
Presenter
Index Name Presenter
|
type: IndexNamePresenter
default: DefaultPresenter.IndexName.present
Optional
The presenter that defines how to display an index, taking as input an |
||
Copy
|
Low-level API
If you want to fully control the SortBy
components and connect them manually, you can use the following components:
Searcher
: TheSearcher
that handles your searches.SortByInteractor
: The logic applied to the index sorting/switching.SelectableSegmentController
: The controller that interfaces with a concrete index list.IndexPresenter
: Optional. The presenter that converts an IndexName to a String output.
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 = .init(appID: "YourApplicationID",
apiKey: "YourSearchOnlyAPIKey",
indexName: "indexDefault")
let alertController = UIAlertController(title: "Change Index",
message: "Please select a new index",
preferredStyle: .actionSheet)
let selectIndexController: SelectIndexController = .init(alertController: alertController)
let indexSegmentInteractor: SortByInteractor = .init(items: [
0 : "indexDefault",
1 : "indexAscendingOrder",
2 : "indexDescendingOrder"
])
indexSegmentInteractor.connectSearcher(searcher: searcher)
indexSegmentInteractor.connectController(selectIndexController) { indexName -> String in
switch indexName {
case "indexDefault": return "Default"
case "indexAscendingOrder": return "Year Asc"
case "indexDescendingOrder": return "Year Desc"
default: return indexName.rawValue
}
}
Customizing your view
The controllers provided by default, like the SelectIndexController
work well when you want to use native UIKit with their default behavior like a UIAlertController
.
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 SelectableSegmentController
protocol.
Protocol
func setSelected(_ selected: Int?)
:
Function called when an index is selected, with the position that is selected.
func setItems(items: [Int: String])
Function called when a new array of indices is defined.
func reload()
Function called when a reload of the list view is required.
var onClick: ((Int) -> Void)?
:
Closure to call when a new index is clicked.
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 SelectIndexController: NSObject, SelectableSegmentController {
let alertController: UIAlertController
public var onClick: ((Int) -> Void)?
public init(alertController: UIAlertController) {
self.alertController = alertController
super.init()
}
public func setSelected(_ selected: Int?) {
// Show a check mark next to the item selected here
}
public func setItems(items: [Int: String]) {
guard alertController.actions.isEmpty else { return }
for item in items {
alertController.addAction(UIAlertAction(title: item.value, style: .default, handler: { [weak self] _ in
self?.onClick?(item.key)
}))
}
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: .none))
}
}
SwiftUI
InstantSearch provides the SelectableSegmentObservableController
data model, which is an implementation of the SelectableSegmentController
protocol adapted for usage with SwiftUI.
SelectableSegmentObservableController
must be connected to the SortByConnector
or SelectableSegmentInteractor
like any other StatsTextController
implementation.
The example of the sort by view using the Menu
component provided by SwiftUI.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct ContentView: View {
@ObservedObject var selectableSegmentObservableController: SelectableSegmentObservableController
var body: some View {
Menu {
let segmentTitles = selectableSegmentObservableController.segmentsTitles
ForEach(0..<segmentTitles.count) { segmentIndex in
Button(segmentTitles[segmentIndex]) {
selectableSegmentObservableController.select(segmentIndex)
}
}
} label: {
if let selectedSegmentIndex = selectableSegmentObservableController.selectedSegmentIndex {
Label(selectableSegmentObservableController.segmentsTitles[selectedSegmentIndex], systemImage: "arrow.up.arrow.down.circle")
}
}
}
}
If you prefer to create a custom index picker SwiftUI view, you can directly use the SelectableSegmentObservableController
as a data model.
It provides segmentsTitles
and selectedSegmentIndex
properties along with select
function to streamline the design process of your custom SwiftUI view.
Check out the example to see this widget in action.