> ## Documentation Index
> Fetch the complete documentation index at: https://algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sort By

> Shows a list of indices for alternative sorting or ranking of search results.

export const Index = () => <Tooltip tip="An Algolia index is a searchable dataset that consists of records and configuration settings. These settings define how the records are searched and ranked.">
    index
  </Tooltip>;

```swift Signature theme={"system"}
SortByConnector(
  searcher: AnyObject & Searchable & IndexNameSettable,
  indicesNames: [IndexName],
  selected: Selected?,
  controller: SelectableSegmentController
)
```

<Card title="Explore example code" icon="github" href="https://github.com/algolia/instantsearch-ios/tree/master/Examples/Showcase">
  Browse the Sort By example code on GitHub.
</Card>

## About this widget

This widget displays a list of indices,
allowing a user to change the way hits are sorting
(with [replica indices](/doc/guides/managing-results/refine-results/sorting/how-to/creating-replicas)).
Another common use case for this widget is to let users switch between different indices.

For this widget to work,
you must define all indices that you pass down as options as replicas of the main <Index />.

## Examples

Instantiate a `SortByConnector`.

```swift Swift icon=code theme={"system"}
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

<ResponseField name="searcher" type="HitsSearcher" required>
  The [`Searcher`](/doc/api-reference/widgets/instantsearch/ios) that handles your searches.
</ResponseField>

<ResponseField name="interactor" type="QueryRuleCustomDataInteractor<Model>" post={["default: .init()"]} required>
  The logic applied to the custom model.
</ResponseField>

<ResponseField name="controller" type="ItemController" post={["default: nil"]}>
  The Controller interfacing with a concrete custom data view.
</ResponseField>

<ResponseField name="presenter" type="Presenter<SearchStats?, Output>" post={["default: nil"]}>
  The Presenter defining how a model appears in the controller.
</ResponseField>

## Presenter

<ParamField body="IndexNamePresenter" type="IndexNamePresenter" default="DefaultPresenter.IndexName.present">
  The presenter that defines how to display an index, taking as input an `indexName` and returning a string.

  ```swift Swift icon=code theme={"system"}
  public static let present: IndexNamePresenter = { indexName in
    return indexName.rawValue
  }
  ```
</ParamField>

## Low-level API

If you want to fully control the `SortBy` components and connect them manually,
you can use the following components:

* `Searcher`. The [`Searcher`](/doc/api-reference/widgets/instantsearch/ios) 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.

```swift Swift icon=code theme={"system"}
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 selected position.

`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

```swift Swift icon=code theme={"system"}
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.

```swift Swift icon=code theme={"system"}
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.
