Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No placemark using MKLocalSearchCompleter

Tags:

ios

swift

mapkit

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)
    }
}

}

like image 829
martomstom Avatar asked Sep 03 '25 15:09

martomstom


1 Answers

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.

like image 71
Carl Avatar answered Sep 05 '25 06:09

Carl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!