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