web-dev-qa-db-ja.com

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)
            }
        }
    }
}

しかし、結果は非常に残念です。

任意のAppleそのような機能を実装するために利用可能なAPI、またはGoogle APIに向かうべきですか?

ありがとうございました

更新-簡単なサンプルプロジェクトを作成しました here 元の回答はSwiftで書かれていたので、Swift 3を使用しました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
    }
}
72

私の答えは、@ George McDonnellに完全に基づいています。最後のものの実装に苦労している人に役立つことを願っています。

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)
    }
}
2
Gogi

間違いなくGoogle APIに向かうべきです。私は長い間AppleのジオコーディングAPIに苦労してきましたが、品質が非常に限られていることを保証できます。

このような低品質の最も明確な例を確認したい場合は、 this 私の質問を確認してください。

GoogleのAPIを使用すると、はるかに正確な結果を得ることができます。さらに、Autocomplete APIがあります。あなたはそれらについてもっと知ることができます こちら

私はそれらを試し、それらを非常にうまく機能させることができました。

1

この問題のサンプルプロジェクトは [〜#〜] here [〜#〜]からダウンロードできます

このサンプルプロジェクトでは、この問題はMKLocalSearchRequestとMapKitを介して達成されます。

Google Places APIのようにオートコンプリートプレースを表示しており、Appleのマップに注釈ポイントを配置できます(Googleマップではなく、あなただけが探していることを願っています)。

ただし、Google Places APIから取得できるほど正確な結果は表示されません。問題は、ジオコーディングデータベースが明らかに完全ではなく、Appleはこの分野をリードする会社ではないということです。Googleはそうです。

サンプルアプリのスクリーンショットを添付して、要件に役立つかどうかを確認できるようにします。

Apple's autocomplete view.

Plotting the annotation point on Apple's map.

これがあなたが探しているものであることを願っています!

1
Apekshit