Как реализовать автоматическое заполнение адреса с помощью Apple Map Kit
Я хочу автоматически заполнить адрес для пользователя так же, как и google api в этой ссылке:
https://developers.google.com/maps/documentation/javascript/places-autocomplete?hl=en
Как я могу реализовать ту же функциональность с помощью набора карт Apple?
Я попытался использовать Geo Coder, я написал это, например:
@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)
}
}
}
}
Однако результаты очень разочаровывают.
Любые API Apple, доступные для реализации такой функциональности, или я должен отправиться в google api?
Спасибо
Ответы
Ответ 1
Обновление - я создал простой пример проекта здесь, используя Swift 3, поскольку первоначальный ответ был написан на Swift 2.
В iOS 9.3 был представлен новый класс под названием MKLocalSearchCompleter
, это позволяет создавать решение для автозаполнения, вы просто передаете queryFragment, как показано ниже:
var searchCompleter = MKLocalSearchCompleter()
searchCompleter.delegate = self
var searchResults = [MKLocalSearchCompletion]()
searchCompleter.queryFragment = searchField.text!
Затем обработайте результаты запроса, используя MKLocalSearchCompleterDelegate
:
extension SearchViewController: MKLocalSearchCompleterDelegate {
func completerDidUpdateResults(completer: MKLocalSearchCompleter) {
searchResults = completer.results
searchResultsTableView.reloadData()
}
func completer(completer: MKLocalSearchCompleter, didFailWithError error: NSError) {
// handle error
}
}
И отобразить результаты адреса в соответствующем формате:
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
}
Затем вы можете использовать объект MKLocalCompletion
для создания экземпляра MKLocalSearch.Request
, таким образом получая доступ к MKPlacemark
и всем другим полезным данным:
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
}
}
Ответ 2
Мой ответ полностью основан на @George McDonnell's. Надеюсь, это поможет ребятам, у которых есть проблемы с реализацией последнего.
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 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)
}
}
Ответ 3
ОБРАЗЕЦ ПРОЕКТА ДЛЯ ЭТОГО ВОПРОСА МОЖНО СКАЧАТЬ С ЗДЕСЬ
В этом примере проекта эта проблема достигается с помощью MKLocalSearchRequest и MapKit.
Он отображает места автозаполнения точно так же, как и API мест Google, и может разместить точку аннотации на карте Apple (не на карте Google, я надеюсь, что это только вы ищете.)
Однако он не дает такого точного результата, как вы можете получить из Google Places API. Поскольку проблема заключается в том, что база геокодирования явно не завершена, и Apple не является компанией, которая возглавляет это поле, - Google.
Прикрепив несколько скриншотов примера приложения, вы сможете увидеть, полезно ли это для ваших требований.
![Apple's autocomplete view.]()
![Plotting the annotation point on Apple's map.]()
Надеюсь, это то, что вы ищете!
Ответ 4
Вы должны обязательно отправиться в Google API. Я долгое время боролся с API API геокодирования Apple, и я могу заверить вас, что они имеют очень ограниченное качество.
Если вы хотите увидеть самый яркий пример такого низкого качества, отметьте этот мой вопрос.
С помощью API Google вы можете добиться гораздо более точных результатов. Кроме того, они имеют API автозаполнения. Вы можете узнать больше о них здесь.
Я попробовал их и сумел заставить их работать очень хорошо.