質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

4671閲覧

[swift] 地図上のアノテーションをタップしたときUILabelを表示する方法

Tajiko

総合スコア12

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2019/03/16 01:17

前提・実現したいこと

iOSアプリを作成しています。
ライブハウスの名前を検索して地図上に周辺のコインロッカーを表示させるアプリです。
場所の情報(latitude,longitude,keyword)をJSON形式で取得し、地図上に該当の場所のAnnotationを表示することまではできました。
最初は吹き出しで詳細情報(keyword)を表示しようとしていましたが、文字列が長い場所もあるので、グーグルマップのように、アノテーションをタップすると画面下部からラベルが出てくるようにしたいのですが、どう書いて良いのかわかりません。

func mapView(myMapView: MKMapView, didSelectAnnotationView view:MKAnnotationView)
がアノテーションが選択されたときのメソッドだということまではわかりました。

発生している問題・エラーメッセージ

わからないのは
① searchLockerメソッドのfor文の中でJSONデータから取り出したkeywordはローカル変数です。
どうやって上記のmapViewメソッドに渡すのか。

②アノテーションの場所によってkeywordの内容も異なります。アノテーションの識別とkeywordの紐付けが行われないと正しい場所に正しいkeywordが表示されないと思うのですが、アノテーションを区別する方法がわかりません。

swift

1import UIKit 2import MapKit 3import SafariServices 4 5class ViewController: UIViewController, UITextFieldDelegate, MKMapViewDelegate { 6 @IBOutlet weak var mapView: MKMapView! 7 @IBOutlet weak var inputText: UITextField! 8 9 var locationManager: CLLocationManager? 10 var numberTitle : [(number: Int, title: String)] = [] 11 var number = 0 12 13 override func viewDidLoad() { 14 super.viewDidLoad() 15 16 //マップ関連の初期化処理 17 self.mapView.delegate = self 18 //テキストフィールドのデリゲート通知先を設定 19 inputText.delegate = self 20 //スイッチは最初オフにしておく 21 swi.isOn = false 22 swi.thumbTintColor = UIColor.yellow 23 //プレースホルダーを設定 24 inputText.placeholder = "ライブハウス名を入力してください" 25 } 26 27 override func didReceiveMemoryWarning() { 28 super.didReceiveMemoryWarning() 29 } 30 31 func textFieldShouldReturn(_ textField: UITextField) -> Bool { 32 //キーボードを閉じる 33 textField.resignFirstResponder() 34 35 //入力された文字を取り出す 36 if let searchKey = textField.text { 37 38 //CLGeocoderインスタンスを取得 39 let geocoder = CLGeocoder() 40 41 //入力された文字から位置情報を取得 42 geocoder.geocodeAddressString(searchKey, completionHandler: { (placemarks, 43 error) in 44 45 //位置情報が存在する場合はunwrapPlacemarksに取り出す 46 if let unwrapPlacemarks = placemarks { 47 //1件目の情報を取り出す 48 if let firstPlacemark = unwrapPlacemarks.first { 49 //位置情報を取り出す 50 if let location = firstPlacemark.location { 51 //位置情報から経度緯度をtargetCoordinateに取り出す 52 let targetCoordinate = location.coordinate 53 //経度緯度をデバッグに表示 54 print(targetCoordinate) 55 56 //MKPointAnnotationインスタンスを取得しピンを生成 57 let pin = MKPointAnnotation() 58 //ピンの置く場所に経度緯度を設定 59 pin.coordinate = targetCoordinate 60 61 //ピンのタイトルを設定 62 pin.title = searchKey 63 //ピンを地図に置く 64 self.mapView.addAnnotation(pin) 65 //経度緯度を中心にして半径500mの範囲を表示 66 self.mapView.region = MKCoordinateRegion(center: targetCoordinate, 67 latitudinalMeters: 500.0, longitudinalMeters: 500.0) 68 69 //コインロッカー検索メソッド発動 70 self.searchLocker(keyword: searchKey) 71 } 72 } 73 } 74 }) 75 } 76 //デフォルト動作を行うのでTRUEを返す 77 return true 78 } 79 80 //jsonの中身を受け取るデータ構造 81 struct Coinlocker: Codable { 82 let latitude : String? 83 let longitude : String? 84 let keyword : String? 85 } 86 87 //ロッカーを検索するメソッド 88 func searchLocker (keyword: String) { 89 90 //検索キーワードをURLエンコードする 91 guard let keyword_encode = keyword.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed) else { 92 return 93 } 94 //リクエストURLの組み立て 95 //guard let req_url = URL(string: "http://192.168.33.10:8000/api.php/?livehouse=(keyword_encode)") else { 96 return 97 } 98 print(req_url) 99 100 //リクエストに必要な情報を生成 101 let req = URLRequest(url: req_url) 102 103 //データ転送を管理するためのセッションを生成 104 let session = URLSession(configuration: .default, delegate: nil 105 , delegateQueue: OperationQueue.main) 106 107 //リクエストをタスクとして登録 108 let task = session.dataTask(with: req, completionHandler: { 109 (data , response , error) in 110 111 //セッションを終了 112 session.finishTasksAndInvalidate() 113 114 //do try catch エラーハンドリング 115 do { 116 //JsonDecoderのインスタンス取得 117 let decoder = JSONDecoder() 118 //受け取ったJSONデータをパース(解析)して格納 119 let json = try decoder.decode([Coinlocker].self, from: data!) 120 121 //ピンを地図に表示する 取得している情報の数だけ処理 122 for item in json { 123 if let latitude = item.latitude , let longitude = item.longitude , let keyword = item.keyword { 124 //String型のjsonのlatitudeとlongitudeをDoubleに変換 125 let doubleLatitude: Double = Double(latitude)! 126 let doubleLongitude: Double = Double(longitude)! 127 //マーカーを表示する 128 let ann = 129 CustomAnnotation.init(coordinate: CLLocationCoordinate2D.init(latitude: doubleLatitude,longitude: doubleLongitude), title: keyword) 130 self.mapView.addAnnotation(ann) 131 } 132 } 133 } catch let error { 134 print(error) 135 } 136 }) 137 //ダウンロード開始 138 task.resume() 139 } 140 141 //アノテーションビューを返すメソッド 142 func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { 143 144 //ユーザの現在地の青まるはそのままなので分岐 145 if(annotation is MKUserLocation) { 146 return nil 147 } else { 148 let identifier = "Pin" 149 var annotationView: MKAnnotationView? = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) 150 if annotationView == nil { 151 annotationView = MKAnnotationView.init(annotation: annotation, reuseIdentifier: identifier) 152 } 153 annotationView?.image = UIImage.init(named: "icon.jpeg") 154 annotationView?.annotation = annotation 155 annotationView?.canShowCallout = false 156 157 return annotationView 158 } 159 } 160 161 func mapView(myMapView: MKMapView, didSelectAnnotationView view:MKAnnotationView){ 162 let label = UILabel(frame: CGRect(x: 40, y:0, width: 200, height: 40)) 163 label.numberOfLines = 0 164 label.backgroundColor = UIColor.cyan 165 } 166}

swift

1import Foundation 2import MapKit 3 4class CustomAnnotation:NSObject, MKAnnotation { 5 public var coordinate: CLLocationCoordinate2D 6 public var title: String? 7 8 init(coordinate: CLLocationCoordinate2D, title: String){ 9 self.coordinate = coordinate 10 self.title = title 11 12 super.init() 13 } 14} 15

JSON

1[ 2 { 3 "latitude": "35.720825", 4 "longitude": "139.927428", 5 "keyword": "JR本八幡駅改札付近北口方面" 6 }, 7 { 8 "latitude": "35.721100", 9 "longitude": "139.927267", 10 "keyword": "都営新宿線本八幡駅 地下1階 駅長事務室の左右" 11 }, 12 { 13 "latitude": "35.721180", 14 "longitude": "139.926283", 15 "keyword": "斉藤ビル" 16 }, 17 { 18 "latitude": "35.721445", 19 "longitude": "139.927562", 20 "keyword": "パティオ本八幡店 M1F踊り場" 21 }, 22 { 23 "latitude": "35.722123", 24 "longitude": "139.926973", 25 "keyword": "ナビパーク八幡第1駐車場" 26 } 27]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

自己解決できました。
func mapView(_ mapView: MKMapView, didSelect view:MKAnnotationView){}
の第二引数がタップされたアノテーションを受け取っていることを知りました。

func mapView(_ mapView: MKMapView, didSelect view:MKAnnotationView){
let annotation = view.annotation
let title = annotation?.title

としてアノテーションのタイトルを参照することができ、UILabelを作成しtitleを表示することができました。
お騒がせしました。

投稿2019/03/26 11:28

Tajiko

総合スコア12

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問