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

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

**参考：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](https://developer.apple.com/documentation/mapkit/mklocalsearchcompleter)で簡単に実装できます。
#POIとは
Point Of Interestの略で、学校や動物園などの場所のことを示します。
![スクリーンショット 2022-01-11 23.27.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577014/1d1a78ba-7533-7b5f-95c1-58124c37f1de.png)
Mapkitの場合、[MKPointOfInterestCategory](https://developer.apple.com/documentation/mapkit/mkpointofinterestcategory)のようにカテゴリーが用意されていて、40種類以上あります。

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

**StoryBoard**
![スクリーンショット 2022-01-12 9.48.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577014/607867a6-41ce-0baf-a856-9f75dbc7f38c.png)
TextFieldとTableViewのシンプルなものにします。
TableViewCellのCellStyleをsubtitleにし、Identifierはcellとします。

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

```swift
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577014/b26a6e0f-5c7f-7556-7da8-4407ec41e29f.gif)
検索はできてますね。
でも、パン屋以外の検索結果も表示されてしまいます。
パン屋を検索するアプリとしてはダメです。

#POIフィルタリングする
ここからが本題です。
pointOfInterestFilterとResultTypeを使って改善していきます。

```swift
let pointOfInterestFilter = MKPointOfInterestFilter(including: [.bakery])
```
まずはMKPointOfInterestFilterのカテゴリーを設定します。今回はベーカリーです。

```swift
   override func viewDidLoad() {
        super.viewDidLoad()
        
        searchCompleter.pointOfInterestFilter = pointOfInterestFilter
        searchCompleter.resultTypes = .pointOfInterest
    }
```
viewDidLoad()にこの二行を追加します。

```swift
searchCompleter.pointOfInterestFilter = pointOfInterestFilter
```
これでsearchComleterにpointOfInterestFilterを適用しています。

```swift
searchCompleter.resultTypes = .pointOfInterest
```
こちらは、searchCompleterのresultTypesをPOIに制限しています。
ちなみに、POIに制限しないと...
![スクリーンショット 2022-01-12 13.07.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577014/a3a78cfe-533c-9a73-a5cc-ca36b537e5a6.png)
このように、地名なども検索に引っかかってしまいます。


では、実際に動かしてみましょう。
![Videotogif (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577014/28016b0f-ac54-8fe2-7450-4bca43a2d038.gif)
ご覧の通り、パン屋だけが検索結果として返ってきています。
うまくいきました。

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

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