3

I am using the following code:

class SearchViewController: UIViewController {

    var searchCompleter = MKLocalSearchCompleter()
    var searchResults = [MKLocalSearchCompletion]()

    @IBOutlet weak var searchResultsTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        searchCompleter.delegate = self
    }
}

extension SearchViewController: UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        searchCompleter.queryFragment = searchText
    }
}

extension SearchViewController: MKLocalSearchCompleterDelegate {

    func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
        searchResults = completer.results
        searchResultsTableView.reloadData()
    }

    func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error) {
        // handle error
    }
}

extension SearchViewController: UITableViewDataSource {

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return searchResults.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let searchResult = searchResults[indexPath.row]
        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: nil)
        cell.textLabel?.text = searchResult.title
        cell.detailTextLabel?.text = searchResult.subtitle
        return cell
    }
}

extension SearchViewController: UITableViewDelegate {

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)

        let completion = searchResults[indexPath.row]

        let searchRequest = MKLocalSearchRequest(completion: completion)
        let search = MKLocalSearch(request: searchRequest)
        search.start { (response, error) in
            let coordinate = response?.mapItems[0].placemark.coordinate
            print(String(describing: coordinate))
        }
    }
}

However this only searches for local and not global. How do I make autocomplete search over global data? I am not able to get if there is an api for iOS for the same and how to achieve it. Help is much appreciated.

I am getting this: enter image description here although I need this: enter image description here

Kuldeep
  • 4,466
  • 8
  • 32
  • 59
Enrik Qaz
  • 243
  • 4
  • 14

2 Answers2

1

I'm no expert on MapKit, but upon reading the documentation it seems to me like you can specify the search region by setting the region parameter in MKLocalSearchRequest. The below code is the example in the official docs.

When specifying your search strings, include a map region to narrow the search results to the specified geographical area.

let request = MKLocalSearchRequest()
request.naturalLanguageQuery = "coffee"

// Set the region to an associated map view's region
request.region = myMapView.region

The myMapView.region is the visible area in your MKMapView. So, if you are getting local results, it's probably because your map is zoomed in on that area.

But, if you show results outside the visible area in the map, then that seems like bad UX, because the user is expecting results in the region which is visible to him. Check out what the current map applications have done. They show results which are within the visible region first, then other regions. This seems to be because of what they say in the last line of the documentation.

Specifying a region does not guarantee that the results will all be inside the region. It is merely a hint to the search engine.

Rakesha Shastri
  • 11,053
  • 3
  • 37
  • 50
  • Hey @rakesha, have a look at the screenshot once. I want to search globally (London, New York, Mumbai all are being searched). This will search in region of myMapView, isn't it? – Enrik Qaz Oct 08 '18 at 09:42
  • @EnrikQaz then create a coordinate region where you want the search to take place and pass that region instead of the map region? https://developer.apple.com/documentation/mapkit/mkcoordinateregion But that seems like bad UX to me. – Rakesha Shastri Oct 08 '18 at 09:43
  • you didn't get me. I dont want to search just for a particular location by saving its map region value. I want to search globally for any region queried. – Enrik Qaz Oct 08 '18 at 09:48
  • @EnrikQaz is there a map visible while you are searching? – Rakesha Shastri Oct 08 '18 at 09:49
  • No, it is just info in the table view as you can see in the question detail. – Enrik Qaz Oct 08 '18 at 09:50
  • But the context is the map which is displayed before it right? – Rakesha Shastri Oct 08 '18 at 09:51
  • There is no map. Please read the code and see the screenshots. There is no map anywhere in this question. it is just autocompletion. – Enrik Qaz Oct 08 '18 at 09:52
  • @EnrikQaz Did you try setting the coordinate region yourself like i suggested? Your second screenshot says **Set location on map**, so i assumed you have a map. – Rakesha Shastri Oct 08 '18 at 09:53
  • That's different. Set location on the map means that the user would search from map and not autocomplete. – Enrik Qaz Oct 08 '18 at 10:06
  • @EnrikQaz _"Did you try setting the coordinate region yourself like i suggested?"_ – Rakesha Shastri Oct 08 '18 at 10:07
  • I'm so sorry. Don't take me as rude. It took me some time to implement the same. – Enrik Qaz Oct 08 '18 at 10:57
  • would you recommend Goggle's sdk for the autocompletion or Apple's mapkit? – Enrik Qaz Oct 08 '18 at 10:58
  • @EnrikQaz I am really sorry. I have no experience whatsoever in `MapKit`. I've explained this in the first line of my answer. Whatever i have posted is the result of what i have learnt today by looking at the documentation. I am sorry that i cannot help you any further than that. – Rakesha Shastri Oct 08 '18 at 10:59
0

I had the same issue and I found that MKLocalSearch.Request (https://developer.apple.com/documentation/mapkit/mklocalsearch/request) works better for global search than MKLocalSearchCompletion. You just have to make sure to make the region the default region, which according to Apple is Global (https://developer.apple.com/documentation/mapkit/mklocalsearchcompleter/1451923-region):

Use this property to limit search results to the specified geographic area. The default value of this property is a region that spans the entire world.

Which can be done as follows:

let request = MKLocalSearch.Request()
request.region = MKCoordinateRegion()

request.naturalLanguageQuery = query
let search = MKLocalSearch(request: request)
  
search.start { response, error in
  guard let response = response else {
    return
   }
    
  self.predictions = response.mapItems
}
Darkisa
  • 1,899
  • 3
  • 20
  • 40