見出し画像

iOSのMapViewの吹き出しタップ処理は初見殺し

こんにちはキッチンカーアーティストのジャマです。

最近はプログラミングの仕事に忙殺されて、ものづくり脳ではなくて、プログラミング脳になってます。

iOSのマップに吹き出しが出せるのですが、それのタップ処理を初めて実装したのですが、初見殺しすぎるので後世の方々が殺されないようにまとめたいと思います。

iOSのマップの吹き出しとは?

スクリーンショット 2022-02-16 12.25.56

上の画像の吹き出しのことです。
赤枠の「タップ」と書かれているタイトル部分
右側の「?」の部分に分かれます。
今回は表示していないですが「タップ」の左側にもボタンをつけることができます。

左ボタン、タイトル、右ボタンの3つの領域からなります。

初見殺しポイント

appleのドキュメントを見ると吹き出しをタップした時のコールバック(iOSではdelegateという)があります。

func mapView(_ mapView: MKMapView,annotationView view: MKAnnotationView,calloutAccessoryControlTapped control: UIControl){
}

一見吹き出し部分をタップすると呼ばれそうなのに、

吹き出しをタップされても呼ばれない

何をすると呼ばれるかというと、先程の?のボタン部分を押すと呼ばれるんです。吹き出しのどこかをタップして、次の処理をさせたいのに、?を押さないと何もできません。

全体をタップして次の処理をする方法がわからず、無事殺されました!

殺されないための護身術

というわけで、私のようにサクッとやられないように対応策を提示しときます。
というか、apple様側が吹き出しのどこ押しても動くdelegateお作りになれば万事解決という話ですが。

まずは同じ疑問を持った人の解決法をネットに見つけたのでそちらになります。

この方法は地図にピンを立てて、そのピンを触った時にコールバックを設定するという方式でした。

非常に残念なことに私のケースでは、ピンを触ることなく吹き出しを表示するという面倒な仕様だったため、この方法が使えなかったです。

この方法にインスパイアされて無事実装できました。

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
       if annotation is MKUserLocation {
           return nil
       }else{
           
           let aview = MKAnnotationView(annotation: annotation, reuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
           aview.image = UIImage(named: "current")
           aview.canShowCallout = true
           
           let tapGesture = UITapGestureRecognizer(target: self, action: #selector (MapSearchView.tapAnnotation(gestureRecognizer:)))
           aview.addGestureRecognizer(tapGesture)
           
           //右のはてなボタンの作成
           let btn = UIButton(type: .custom)
           btn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
           btn.setImage(UIImage(named: "hatena"), for: .normal)
           aview.rightCalloutAccessoryView = btn
           
           //ラベルの作成
           let label = UILabel()
           label.text = Const.searchLocationTitle
           label.font = UIFont.boldSystemFont(ofSize: 15)
           label.textColor = UIColor(hex: Const.searchLocationColor)
           label.isUserInteractionEnabled = true
           aview.detailCalloutAccessoryView = label
           aview.isUserInteractionEnabled = true
           
           
           return aview
           
       }
   }わ
@objc func tapAnnotation(gestureRecognizer: UITapGestureRecognizer){
    //タップ処理
}

私の場合はviewFor annotationでMKAnnotationViewを作っていたので、そこでgestureを作って、annotationviewに付与することにしました。
ソースコード的には上記になります。しかし、このソース、imageとかUIColorを16進数で呼び出す処理などが別途必要なので、コピペでは動かないです。よちらご容赦下さい。

マップの吹き出し全体をタップしたい時はannotationviewに直接tap gestureを付与して下さい。

この記事が気に入ったらサポートをしてみませんか?