I want to search for Cities only but MKLocalSearchRequest/MKLocalSearch can not be filtered. I tried MKLocalSearchCompleter but this is not giving me any placemarks... only name and subtitle. Is there a way to get placemarks from MKLocalSearchCompleter?
I did the following to make it work. But I don't think it is good practice to call MKLocalSearchRequest again inside didSelectRowAt indexPath. But I can not save the first result and get the correct item out of this array in didSelectRowAt
var searchCompleter = MKLocalSearchCompleter()
var searchResults = [MKLocalSearchCompletion]()
extension SearchTableViewController : UISearchResultsUpdating {
public func updateSearchResults(for searchController: UISearchController) {
    guard let searchBarText = searchController.searchBar.text else { return }
    searchCompleter.queryFragment = searchBarText
    if searchCompleter.results.count > 0 {
        let searchRequest = MKLocalSearchRequest()
        let search = MKLocalSearch(request: searchRequest)
        search.start { (response, error) in }
    }
}
}
extension SearchTableViewController: MKLocalSearchCompleterDelegate {
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
    searchResults = completer.results
    self.tableView.reloadData()
}
func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error) {
    // handle error
}}
extension SearchTableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return searchResults.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "SearchCell")!
   // let selectedItem = matchingItems[indexPath.row]
    let searchResult = searchResults[indexPath.row]
    cell.textLabel?.text = searchResult.title
    cell.detailTextLabel?.text = searchResult.subtitle
    return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath:IndexPath) {
    let searchRequest = MKLocalSearchRequest(completion: searchCompleter.results[indexPath.row])
    let search = MKLocalSearch(request: searchRequest)
    search.start { (response, error) in
        let placemark = response?.mapItems[0].placemark
        self.onSearchMapChanged?(placemark!.coordinate)
    }
}
}
I think that’s how Apple intended this “dual” API is meant to be applied. Their approach reduces the amount of data that is returned in the list.
Here’s a clean implementation of the approach.
The MKLocalSearchCompleter enables you to provide suggested complete terms for fragments "as a user taps them in". The MKLocalSearch returns the details of locations but only for a search term when the user has finished entering it and taps a Search button.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With