The dirtiest and easiest solution (works as you see fit), just create a second tableView. For example (Swift 3):
tableView = UITableView(frame: CGRect.zero, style: .grouped) tableView.delegate = self tableView.dataSource = self tableView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(tableView) let cnt1 = NSLayoutConstraint(item: tableView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: 0) let cnt2 = NSLayoutConstraint(item: tableView, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1, constant: 0) let cnt3 = NSLayoutConstraint(item: view, attribute: .trailing, relatedBy: .equal, toItem: tableView, attribute: .trailing, multiplier: 1, constant: 0) let cnt4 = NSLayoutConstraint(item: view, attribute: .bottom, relatedBy: .equal, toItem: tableView, attribute: .bottom, multiplier: 1, constant: -1) constraintTableViewBottom = cnt4 view.addConstraints([cnt1, cnt2, cnt3, cnt4]) let tableView2 = UITableView(frame: CGRect.zero, style: .grouped) tableView2.sectionIndexColor = .black tableView2.sectionIndexBackgroundColor = .clear tableView2.delegate = self tableView2.dataSource = self tableView2.translatesAutoresizingMaskIntoConstraints = false tableView2.backgroundColor = .clear view.addSubview(tableView2) let cnt5 = NSLayoutConstraint(item: tableView2, attribute: .height, relatedBy: .equal, toItem: view, attribute: .height, multiplier: 1, constant: 0) let cnt6 = NSLayoutConstraint(item: tableView2, attribute: .centerY, relatedBy: .equal, toItem: view, attribute: .centerY, multiplier: 1, constant: 0) let cnt7 = NSLayoutConstraint(item: view, attribute: .trailing, relatedBy: .equal, toItem: tableView2, attribute: .trailing, multiplier: 1, constant: 0) let cnt8 = NSLayoutConstraint(item: tableView2, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: 13) tableView2.addConstraint(cnt8) view.addConstraints([cnt5, cnt6, cnt7])
and
func sectionIndexTitles(for tableView: UITableView) -> [String]? { if tableView == self.tableView { return nil } if searchController.isActive && searchController.searchBar.text != "" { return filteredCells.keys.map { return sections[$0] } } return sections } func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int { self.tableView.scrollToRow(at: IndexPath(row: 0, section: index), at: .top, animated: true) return sections.index(of: title)! } final func numberOfSections(in tableView: UITableView) -> Int { if tableView != self.tableView { return 0 } return sections.count }
and for example
final func updateSearchResults(for searchController: UISearchController) { filterCells(searchText: searchController.searchBar.text!) tableView.reloadSectionIndexTitles() }