Hits
HitsConnector<Hit: Codable>( appID: ApplicationID, apiKey: APIKey, indexName: IndexName, infiniteScrolling: InfiniteScrolling, showItemsOnEmptyQuery: Bool, filterState: FilterState, controller: HitsController )
About this widget
The Hits component displays a list of search results. The component automatically reloads results when new hits are fetched from Algolia.
HitsConnector is a generic class you can customize by implementing a class or structure that represents your record and conforms to the Codable protocol.
If, for some reason, the engine can’t parse a record into the type you provided, the onError event of the Interactor instance will be triggered.
If you prefer to deal with raw JSON objects, set JSON as the type of record and use the rawHitAtIndex(_ row: Int) -> [String: Any]? method to access a hit.
For guidance on how to search across more than one index, read the multi-index search guide.
If there are no hits, you should display a message to users and clear filters so they can start over.
Examples
Define the custom type representing the hits in your index conforming to Codable protocol.
1
2
3
struct CustomHitModel: Codable {
  let name: String
}
Instantiate a HitsConnector and launch an initial search on its searcher.
1
2
3
4
5
6
7
8
9
10
let filterState: FilterState  = .init()
let hitsTableViewController = CustomHitsTableViewController()
let hitsConnector = HitsConnector<CustomHitModel>(appID: "YourApplicationID",
                                              apiKey: "YourSearchOnlyAPIKey",
                                              indexName: "YourIndexName",
                                              filterState: filterState,
                                              controller: hitsTableViewController)
hitsConnector.searcher.search()
Parameters
| Parameter | Description | 
|---|---|
          
            searcher
          
         | 
        
           
                
                type: HitsSearcher | PlacesSearcher
                
               
              
                
                        Required
                
               
          The   | 
      
          
            interactor
          
         | 
        
           
                
                type: HitsInteractor
                
               
              
                
                        Required
                
               
          The logic applied to the hits.  | 
      
          
            filterState
          
         | 
        
           
                
                type: FilterState
                
               
              
                
                    Optional
                
               
          The   | 
      
          
            appID
          
         | 
        
           
                
                type: ApplicationID
                
               
              
                
                        Required
                
               
          The ID of your application.  | 
      
          
            placesAppID
          
         | 
        
           
                
                type: ApplicationID
                
               
              
                
                        Required
                
               
          The ID of your Places application.  | 
      
          
            apiKey
          
         | 
        
           
                
                type: APIKey
                
               
              
                
                        Required
                
               
          Your application API Key. Be sure to use your Search-only API key.  | 
      
          
            indexName
          
         | 
        
           
                
                type: IndexName
                
               
              
                
                        Required
                
               
          Name of the index to search.  | 
      
          
            infiniteScrolling
          
         | 
        
           
                
                type: InfiniteScrolling
                
               
              
                
                  default: .on(withOffset: 5)
                
               
              
                
                    Optional
                
               
          Whether infinite scrolling is enabled.   | 
      
          
            showItemsOnEmptyQuery
          
         | 
        
           
                
                type: Bool
                
               
              
                
                  default: true
                
               
              
                
                    Optional
                
               
          If   | 
      
          
            controller
          
         | 
        
           
                
                type: HitsController
                
               
              
                
                  default: nil
                
               
              
                
                    Optional
                
               
          The controller interfacing with a concrete hits view.  | 
      
Low-level API
To fully control the Hits components and connect them manually, use the following components:
[Searcher`](/doc/api-reference/widgets/instantsearch/ios/): handles your searches.HitsInteractor: the logic applied to the hits.HitsController: the controller that interfaces with a concrete hits view.FilterState: the current state of the filters.
1
2
3
4
5
6
7
8
9
10
11
12
let searcher = HitsSearcher(appID: "YourApplicationID",
                            apiKey: "YourSearchOnlyAPIKey",
                            indexName: "YourIndexName")
let filterState: FilterState  = .init()
let hitsInteractor: HitsInteractor<CustomHitModel> = .init()
let hitsTableViewController = CustomHitsTableViewController()
hitsInteractor.connectSearcher(searcher)
hitsInteractor.connectFilterState(filterState)
hitsInteractor.connectController(hitsTableViewController)
searcher.search()
Now, each time you launch a new search:
- The 
Searcherreceives new results and transmit them toHitsInteractor - The 
HitsInteractorparses search results and notifiesHitsController - The 
HitsControllerrefreshes the view presenting the hits 
HitsController
The default controllers, HitsTableViewController and HitsCollectionViewController, allow you to create a basic Hits view based on UITableView and UICollectionView components from UIKit.
You must configure these controllers using the TableViewCellConfigurable/CollectionViewCellConfigurable implementation protocols that define how your hit model is bound to a concrete cell class.
Here is an example of the implementation using the UITableViewCell and CustomHitModel defined above.
1
2
3
4
5
6
7
8
9
10
11
struct CustomCellConfigurator: TableViewCellConfigurable {
  let model: CustomHitModel
  
  init(model: CustomHitModel, indexPath: IndexPath) {
    self.model = model
  }
  
  func configure(_ cell: UITableViewCell) {
    cell.textLabel?.text = model.name
  }
}
Define a convenient type alias for your view controller using the CellConfigurable implementation.
1
typealias CustomHitsTableViewController = HitsTableViewController<CustomCellConfigurator>
Customization
You can subclass the HitsTableViewController or HitsCollectionViewControllerto customize their behavior.
1
2
3
class MoreCustomHitsTableViewController: HitsTableViewController<CustomCellConfigurator> {
  ...  
}
Customizing your view
The default controllers, HitsTableViewController and HitsCollectionViewController, work well when using native UIKit components with default behaviors.
If you want to use another component as a hits view or introduce some custom behavior to the already provided UIKit component, you can create a controller conforming to the HitsController protocol.
Protocol
var hitsSource: DataSource?:
Reference to an entity providing a list of hits.
func reload():
Function called when we require a reload of the hits view.
func scrollToTop():
Function called when scrolling to the top of the hits view.
Implementation example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class CustomHitsTableViewController: NSObject, HitsController {
  public let tableView: UITableView
  
  public weak var hitsSource: HitsInteractor<Item>?
  public init(tableView: UITableView) {
    self.tableView = tableView
  }
  public func reload() {
    tableView.reloadData()
  }
  public func scrollToTop() {
    guard tableView.numberOfRows(inSection: 0) != 0 else { return }
    let indexPath = IndexPath(row: 0, section: 0)
    self.tableView.scrollToRow(at: indexPath, at: .top, animated: false)
  }
}
SwiftUI
InstantSearch provides the HitsList SwiftUI view, which you can embed in your views.
It uses HitsObservableController as a data model. HitsObservableController is an implementation of the HitsController protocol adapted for usage with SwiftUI.
HitsObservableController must be connected to the HitsConnector or HitsInteractor like any other HitsController implementation.
You should define the view representing a single hit.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct HitItem: Codable {
  let name: String
}
struct ContentView: View {
  @ObservedObject var hitsController: HitsObservableController<HitItem>
  var body: some View {
    HitsList(hitsController) { (hit, _) in
      // declare the view representing a single hit
      VStack(alignment: .leading, spacing: 10) {
        Text(hit?.name ?? "")
        Divider()
      }
    } noResults: {
      Text("No Results")
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
  }
}
If you prefer to create a custom SwiftUI view that presents the list hits, use HitsObservableController as a data model.
It provides the hits property to streamline the design process of your custom SwiftUI view.
The notifyAppearanceOfHit(atIndex) function of HitsObservableController might be called on appearance of each hit to ensure the correct operation of the infinite scrolling feature.
Result metadata and Hit structure
Each hit returned by Algolia is enriched with search metadata, like highlightResult, objectID, and snippetResult.
InstantSearch provides an easy way to parse these using the Hit wrapper structure. This generic structure encapsulates your record type and gives strongly-typed access to the metadata of a hit.
For example, consider the following record structure:
1
2
3
4
5
6
7
8
9
10
11
12
13
struct Movie: Codable {
  let title: String
  let year: Int
}
/* An appropriate structure for representing a record in the following JSON format:
{
  "title": "Titanic",
  "year": 1997
}
*/
Conforming to the Codable protocol, the record is ready to use with the HitsInteractor as follows:
1
let hitsInteractor = HitsInteractor<Movie>()
However, by doing this, the engine will ignore all the hit metadata.
To keep this metadata, wrap your record structure into the provided Hit structure.
1
let hitsInteractor = HitsInteractor<Hit<Movie>>()
You can extract your Movie object by accessing the object field of Hit:
1
2
let movieHit: Hit<Movie> = hitsInteractor.hit(atIndex: ...)
let movie: Movie = movieHit.object
The Hit structure gives access to the following fields:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Hit identifier attributed by Algolia
let objectID: String
// Wrapped record object
let object: T
// Snippeted attributes.
let snippetResult: TreeModel<SnippetResult>?
// Highlighted attributes. Each attribute contains an object or an array of objects (if the attribute in question is an array) with the following attributes.
let highlightResult: TreeModel<HighlightResult>?
// Ranking information.
let rankingInfo: RankingInfo?
// Geolocation information
let geolocation: Point?