検索した場所にピンを刺す

## ゴール
[以前](https://qiita.com/toshiya_arakawa/items/48b2730c7407c2f5e240)、画面に地図を表示し、ピンを決め打ちで指すことができるようになった。このピンを、UIから取得した任意の場所に刺せるようにしたい。

## 調査
- 普通にstoryboardでボタン、ラベルを配置すると、地図がそれらより全面に描画される？ため、検索欄などを儲けることができない。
- 地点検索の実装に関して、公式にめちゃくちゃご親切に[書いてある](https://developers.google.com/maps/documentation/places/ios-sdk/autocomplete)けど、実行して見ると動かない部分もあり、理解が追いつかないので一つずつ進める。
- 地図より前面にボタンなどを配置しようと思うと、storyboardではなく、ViewController.swiftのPG上で実装する必要がありそう。実行の順番の問題？
- <del>delegateについて気になったので[調査](https://www.sejuku.net/blog/33867)。ほぼinterefaceじゃんと思いましたが、厳密には[違う](https://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=23322&forum=7)みたい。</del>全然違った。[delegate](https://qiita.com/jumpyoshim/items/7667e0cc81ad91016f03)
- 地名や建物名から検索を行う機能はいくつかあるみたいだが、[この３つ](https://developers-jp.googleblog.com/2016/12/address-geocoding-in-google-maps-apis.html)（ジオコーディング、オートコンプリートサービス、プレイス検索）の中だと、曖昧検索の結果の中から1つを選択することのできる、「オートコンプリートサービス」が良い。

## 実装
<del>ボタンを配置する。</del>

```swift
func makeButton() {
    let btnLaunchAc = UIButton(frame: CGRect(x: 25, y: 25, width: 80, height: 80))
    btnLaunchAc.backgroundColor = .clear
    btnLaunchAc.setTitle("Pos", for: .normal)
    btnLaunchAc.setTitleColor(.blue, for: .normal)
    btnLaunchAc.addTarget(self, action: #selector(getMyPosition), for: .touchUpInside)
    self.view.addSubview(btnLaunchAc)
}
```

<del>ラベル×2を配置する。</del>

```swift
func makeLabel() {
    nameLabel = UILabel(frame: CGRect(x:105, y:25, width:250, height:40))
    addressLabel = UILabel(frame: CGRect(x:105, y:65, width:250, height:40))
    nameLabel.textColor = .blue
    addressLabel.textColor = .blue
    //nameLabel.backgroundColor = .white
    //addressLabel.backgroundColor = .white
    nameLabel.text = "name"
    addressLabel.text = "address"
    self.view.addSubview(nameLabel)
    self.view.addSubview(addressLabel)
}
```

テキストフィールドを配置

```swift
func makeTextField() {
    textField = UITextField()
    textField.frame = CGRect(x: 10, y: 100, width: UIScreen.main.bounds.size.width-20, height: 38)
    textField.placeholder = "目的地"
    textField.keyboardType = .default
    textField.borderStyle = .roundedRect
    textField.returnKeyType = .done
    textField.clearButtonMode = .always
    self.view.addSubview(textField)
}
```

完了ボタンを押すとキーボードが閉じるように以下3点を追加（[参考](https://qiita.com/jumpyoshim/items/4b8b5f2297910d7f3d1b)）

```swift
//1
class ViewController: UIViewController, CLLocationManagerDelegate, UITextFieldDelegate  {

//2
textField.delegate = self

//3
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    self.view.endEditing(true)
    return false
}
```

<del>[こちら](https://note.com/iga34engineer/n/n25282ecb534e)を参考に、テキストフィールドの値が変わるたびに呼ばれる関数を定義（オートコンプリートを呼びたい）</del>

```swift
// textFieldに対して追加
textField.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: UIControl.Event.editingChanged)

// 関数を追加
@objc func textFieldDidChange(_ textFiled: UITextField) {

}
```

→オートコンプリートを勘違いしてた。文字が変更されるたびに呼ぶ必要はなく、入力が開始されるタイミングで一度呼べば良いので、実装を以下に変更。（[参考](https://developers.google.com/maps/documentation/places/ios-sdk/autocomplete#add_a_full-screen_control)）

```swift
// textFieldに対して追加
textField.addTarget(self, action: #selector(self.textFieldChange(_:)), for: UIControl.Event.editingDidBegin)

// 関数を追加
@objc func textFieldChange(_ textFiled: UITextField) {
}
```

テキストフィールドが呼ばれたタイミングで、別画面が表示されるよう、`textFieldChange`関数内に以下を追加する。

```swift
@objc func textFieldChange(_ textFiled: UITextField) {
    // ViewController?を追加
    let autocompleteController = GMSAutocompleteViewController()

    // delegateを指定する
    autocompleteController.delegate = self

    // autocompleteControllerを表示する
    present(autocompleteController, animated: true, completion: nil)
}
```

`autocompleteController`で行われる処理を実装する。

```swift
extension ViewController: GMSAutocompleteViewControllerDelegate {
    // ①
    func viewController(_ viewController: GMSAutocompleteViewController, didAutocompleteWith place: GMSPlace) {
        textField.text = place.name
        dismiss(animated: true, completion: nil)
    }

    // ②
    func viewController(_ viewController: GMSAutocompleteViewController, didFailAutocompleteWithError error: Error) {
        // TODO
    }

    // ③
    func wasCancelled(_ viewController: GMSAutocompleteViewController) {
        dismiss(animated: true, completion: nil)
    }
}
```

`GMSAutocompleteViewControllerDelegate`に飛んで、各メソッドの役割を確認してみる。
①
利用可能なオートコンプリート予測から場所が選択されたときに呼び出されます。 
このメソッドの実装では、View Controller が終了しないため、View Controller を終了する必要があります。
自分自身をdismissしてください。
②
オートコンプリートの予測または場所を取得するときに再試行不可能なエラーが発生したときに呼び出されます
詳細。 再試行不可能なエラーは、すぐに修正される可能性が低いエラーとして定義されます
操作を再試行してください。
③
ユーザーが |GMSAutocompleteViewController| の [キャンセル] ボタンをタップしたときに呼び出されます。
このメソッドの実装では、View Controller が終了しないため、View Controller を終了する必要があります。
自分自身をdismissしてください。

エラー処理は一旦置いておいて、予測された場所の一覧の中から一つを選んだときに、テキストフィールドに値が入るように実装した。

![スクリーンショット 2021-05-29 11.18.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391844/0984a04a-eb76-a6e3-beb3-7a70b7c230e9.png)

![スクリーンショット 2021-05-29 11.18.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391844/0ffaf57f-d4f3-6f9e-cb45-3795de491c7e.png)

あとは、選択した地名やアドレスから、緯度軽度を取得して、ピンを指す値として渡してあげる。
マーカーと、カメラの位置を指定する部分を関数化して、初めに呼ばれるとき以外は、指定したカメラのポジションに移動するように実装

```swift
func PointPlace(pos: CLLocationCoordinate2D, title: String?) {
    camera = GMSCameraPosition.camera(withTarget: pos, zoom: 10.0)
    if(first){
        mapView = GMSMapView.map(withFrame: self.view.frame, camera: camera)
        self.view.addSubview(mapView)
    }else{
        self.mapView.animate(to: camera)
    }

    marker.position = pos
    marker.title = title
    marker.map = mapView
}
```

上記①の中で、位置と名前を渡してあげる。

```swift
func viewController(_ viewController: GMSAutocompleteViewController, didAutocompleteWith place: GMSPlace) {
    textField.text = place.name
    // 位置と名前を渡す
    PointPlace(pos: place.coordinate, title: place.name)
    dismiss(animated: true, completion: nil)
}
```

できた！

![スクリーンショット 2021-05-29 17.43.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391844/e4fb6f83-e64d-9f72-dfd3-57105d7f9c58.png)
![スクリーンショット 2021-05-29 17.43.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391844/aeeb2155-7be8-032c-0791-8688254acae8.png)
![スクリーンショット 2021-05-29 17.44.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391844/f6902923-79d0-fc07-5977-76bddd1791d1.png)