前提・実現したいこと
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]
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。