How to implement auto-complete for address using Apple Map Kit

Mostafa Mohamed Raafat picture Mostafa Mohamed Raafat · Oct 28, 2015 · Viewed 27.1k times · Source

I want to auto-complete the address for the user as same as what google api provides in this link:

https://developers.google.com/maps/documentation/javascript/places-autocomplete?hl=en

How can i implement the same functionality using apple map kit?

I have tried to use the Geo Coder, i wrote this for example:

@IBAction func SubmitGeoCode(sender: AnyObject) {

    let address = "1 Mart"
    let coder = CLGeocoder()

    coder.geocodeAddressString(address) { (placemarks, error) -> Void in

        for placemark in placemarks! {

            let lines = placemark.addressDictionary?["FormattedAddressLines"] as? [String]

            for addressline in lines! {
                print(addressline)
            }
        }
    }
}

However the results are very disappointing.

Any Apple APIs available to implement such functionality, or should i head for google api ?

Thank you

Answer

George McDonnell picture George McDonnell · Jul 21, 2016

Update - I've created a simple example project here using Swift 3 as the original answer was written in Swift 2.

In iOS 9.3 a new class called MKLocalSearchCompleter was introduced, this allows the creation of an autocomplete solution, you simply pass in the queryFragment as below:

var searchCompleter = MKLocalSearchCompleter()
searchCompleter.delegate = self
var searchResults = [MKLocalSearchCompletion]()

searchCompleter.queryFragment = searchField.text!

Then handle the results of the query using the MKLocalSearchCompleterDelegate:

extension SearchViewController: MKLocalSearchCompleterDelegate {

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

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

And display the address results in an appropriate format:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> 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
}

You can then use a MKLocalCompletion object to instantiate a MKLocalSearch.Request, thus gaining access to the MKPlacemark and all other useful data:

let searchRequest = MKLocalSearch.Request(completion: completion!)
let search = MKLocalSearch(request: searchRequest)
search.startWithCompletionHandler { (response, error) in
    if error == nil {
        let coordinate = response?.mapItems[0].placemark.coordinate
    }
}