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

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

  • iOS 6 Saving/Restoring app state feature
  • UIImage's drawInrect: smoothes image
  • Hiding preferences items in the settings bundle
  • Different image when button from storyboard tapped
  • iOS 7 - Long running background task
  • Configuring Cocoapods with an existing static library and iOS application
  • 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

    3 Solutions Collect From Internet About “How to implement auto-complete for address using Apple Map Kit”

    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 MKLocalSearchRequest, thus gaining access to the MKPlacemark and all other useful data:

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

    My answer is fully based on @George McDonnell’s. I hope it helps to guys who has troubles with implementing of the last one.

    import UIKit
    import MapKit
    
    class ViewController: UIViewController {
    
        @IBOutlet weak var searchBar: UISearchBar!
        @IBOutlet weak var tableVIew: UITableView!
    
        //create a completer
        lazy var searchCompleter: MKLocalSearchCompleter = {
            let sC = MKLocalSearchCompleter()
            sC.delegate = self
            return sC
        }()
    
        var searchSource: [String]?
    }
    
    extension ViewController: UISearchBarDelegate {
        func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
            //change searchCompleter depends on searchBar's text
            if !searchText.isEmpty {
                searchCompleter.queryFragment = searchText
            }
        }
    }
    
    extension ViewController: UITableViewDelegate, UITableViewDataSource {
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return searchSource?.count ?? 0
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            //I've created SearchCell beforehand; it might be your cell type
            let cell = self.tableVIew.dequeueReusableCell(withIdentifier: "SearchCell", for: indexPath) as! SearchCell
    
            cell.label.text = self.searchSource?[indexPath.row]
    //            + " " + searchResult.subtitle
    
            return cell
        }
    }
    
    extension ViewController: MKLocalSearchCompleterDelegate {
        func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
            //get result, transform it to our needs and fill our dataSource
            self.searchSource = completer.results.map { $0.title }
            DispatchQueue.main.async {
                self.tableVIew.reloadData()
            }
        }
    
        func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error) {
            //handle the error
            print(error.localizedDescription)
        }
    }
    

    You should definitely head for Google APIs. I have struggled for a long time with Apple’s geocoding APIs and I can assure you that they are of very limited quality.

    If you want to see the clearest example of such low quality, check this question of mine.

    With Google’s APIs you can achieve much more accurate results. In addition, they have Autocomplete APIs. You can find out more about them here.

    I have tried them and managed to make them working quite nicely.