LoginSignup
1
0

More than 1 year has passed since last update.

[Swift]MKLocalSearchCompleterをPOIフィルタリングして改善してみる!

Last updated at Posted at 2022-01-12

はじめに

唐突ですが、あなたはパン屋を検索できるアプリを作っているとします。
オートコンプリートで簡単に検索できる機能を実装しようとしますが、関係のないお店が出てきてしまうかもしれません。
今回はパン屋のみを検索できるように改善してみようと思います。

参考:WWDC19 What’s New in MapKit and MapKit JS
https://developer.apple.com/videos/play/wwdc2019/236/

開発環境

Xcode 13.0
Swift 5.5

オートコンプリートとは

文字を途中まで入力すると、候補を出してくれる機能のことです。
MapkitのMKLocalSearchCompleterで簡単に実装できます。

POIとは

Point Of Interestの略で、学校や動物園などの場所のことを示します。
スクリーンショット 2022-01-11 23.27.45.png
Mapkitの場合、MKPointOfInterestCategoryのようにカテゴリーが用意されていて、40種類以上あります。

基本の実装

まずは簡単に検索機能を実装してみます。

StoryBoard
スクリーンショット 2022-01-12 9.48.46.png
TextFieldとTableViewのシンプルなものにします。
TableViewCellのCellStyleをsubtitleにし、Identifierはcellとします。

オートコンプリートを実装

import UIKit
import MapKit

class ViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!
    @IBOutlet weak var tableView: UITableView!

    var searchCompleter = MKLocalSearchCompleter()

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self

        searchCompleter.delegate = self
    }

    @IBAction func textEditingChanged(_ sender: Any) {
        searchCompleter.queryFragment = textField.text ?? ""
    }

}

extension ViewController: MKLocalSearchCompleterDelegate {

    func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
        tableView.reloadData()
    }

    func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error) {
        print("error: \(error)")
    }

}

extension ViewController: UITableViewDataSource, UITableViewDelegate {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {![Something went wrong]()
        return searchCompleter.results.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") else { return UITableViewCell() }
        return cell
    }

}

とても簡単に実装できました。
これでTextFieldに入力するとパン屋が検索できるはずです!
試しに僕の好きな『パンのトラ』を検索してみます。

Videotogif (1).gif
検索はできてますね。
でも、パン屋以外の検索結果も表示されてしまいます。
パン屋を検索するアプリとしてはダメです。

POIフィルタリングする

ここからが本題です。
pointOfInterestFilterとResultTypeを使って改善していきます。

let pointOfInterestFilter = MKPointOfInterestFilter(including: [.bakery])

まずはMKPointOfInterestFilterのカテゴリーを設定します。今回はベーカリーです。

   override func viewDidLoad() {
        super.viewDidLoad()

        searchCompleter.pointOfInterestFilter = pointOfInterestFilter
        searchCompleter.resultTypes = .pointOfInterest
    }

viewDidLoad()にこの二行を追加します。

searchCompleter.pointOfInterestFilter = pointOfInterestFilter

これでsearchComleterにpointOfInterestFilterを適用しています。

searchCompleter.resultTypes = .pointOfInterest

こちらは、searchCompleterのresultTypesをPOIに制限しています。
ちなみに、POIに制限しないと...
スクリーンショット 2022-01-12 13.07.27.png
このように、地名なども検索に引っかかってしまいます。

では、実際に動かしてみましょう。
Videotogif (2).gif
ご覧の通り、パン屋だけが検索結果として返ってきています。
うまくいきました。

これらの検索結果を利用してLocalSearchにかけてあげれば、緯度経度なども取得できるようになります。
また別でその記事を書いてみようかなと思います。

では、良きパンライフを!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0