前提・実現したいこと
MKLocalSearchを利用して、キーワード検索で何個かのピンを立てています。
このピンはstart(completionHandler:)
メソッドの引数に指定した関数内のfor文の中で定義し、それを配列に格納しています。
Swift
1var searchAnnotationArray = [MKPointAnnotation]() 2var searchAnnotationTitleArray = [String]() 3var searchAnnotationLatArray = [String]() 4var searchAnnotationLonArray = [String]()
Swift
1func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { 2 print("検索") 3 4 // キーボードをとじる 5 self.view.endEditing(true) 6 7 // 検索条件を作成 8 let request = MKLocalSearch.Request() 9 request.naturalLanguageQuery = placeSearchBar.text 10 11 // 検索範囲はMKMapViewと同じ 12 request.region = mapView.region 13 14 let localSearch = MKLocalSearch(request: request) 15 localSearch.start(completionHandler: LocalSearchCompHandler(response:error:)) 16} 17 18// start(completionHandler:)の引数 19func LocalSearchCompHandler(response: MKLocalSearch.Response?, error: Error?) -> Void { 20 for searchLocation in (response?.mapItems)! { 21 if error == nil { 22 let searchAnnotation = MKPointAnnotation() 23 // ピンの座標 24 let center = CLLocationCoordinate2DMake(searchLocation.placemark.coordinate.latitude, searchLocation.placemark.coordinate.longitude) 25 searchAnnotation.coordinate = center 26 27 let latStr = center.latitude.description 28 let lonStr = center.longitude.description 29 30 // 配列に検索した位置の緯度と経度をセット 31 searchAnnotationLatArray.append(latStr) 32 searchAnnotationLonArray.append(lonStr) 33 34 // タイトルに場所の名前を表示 35 searchAnnotation.title = searchLocation.placemark.name 36 // ピンを立てる 37 mapView.addAnnotation(searchAnnotation) 38 39 // 配列にピンをセット 40 searchAnnotationArray.append(searchAnnotation) 41 // 配列に場所の名前をセット 42 searchAnnotationTitleArray.append(searchAnnotation.title ?? "") 43 44 } else { 45 print("error") 46 } 47 } 48}
なぜ配列に格納しているかというと、prepare
メソッドで遷移先に値を渡したいためです。
Swift
1override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 2 guard let identifier = segue.identifier else { 3 return 4 } 5 6 if identifier == "toReceiveVC" { 7 let receiveVC = segue.destination as! ReceiveViewController 8 receiveVC.place = self.searchAnnotationTitleArray[0] // index番号がわからないので暫定的に0を指定 9 receiveVC.lat = self.searchAnnotationLatArray[0] // index番号がわからないので暫定的に0を指定 10 receiveVC.lon = self.searchAnnotationLonArray[0] // index番号がわからないので暫定的に0を指定 11 } 12}
現在、遷移先には暫定的に0番目の情報を渡しています。
発生している問題
選択されているピンのindex番号の取得方法、それ以前にピンの選択状態を見極める方法がわかりません。selectAnnotation(_:animated:)
メソッド、selectedAnnotations
プロパティなど関連しそうなものの公式ドキュメントは読んでみましたが、わからず。
ソースコード全文
#####ViewController.swift
Swift
1import UIKit 2import MapKit 3import CoreLocation 4 5class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate, UISearchBarDelegate { 6 7 @IBOutlet weak var mapView: MKMapView! 8 var locManager: CLLocationManager! 9 @IBOutlet weak var placeSearchBar: UISearchBar! 10 11 var searchAnnotationArray = [MKPointAnnotation]() 12 var searchAnnotationTitleArray = [String]() 13 var searchAnnotationLatArray = [String]() 14 var searchAnnotationLonArray = [String]() 15 16 override func viewDidLoad() { 17 super.viewDidLoad() 18 // Do any additional setup after loading the view. 19 20 mapView.delegate = self 21 22 locManager = CLLocationManager() 23 locManager.delegate = self 24 25 placeSearchBar.delegate = self 26 27 // 位置情報利用の許可を得る 28 locManager.requestWhenInUseAuthorization() 29 30 // 縮尺 31 var region: MKCoordinateRegion = mapView.region 32 region.span.latitudeDelta = 0.02 33 region.span.longitudeDelta = 0.02 34 mapView.setRegion(region, animated: true) 35 36 // ユーザーを中心に地図を表示 37 mapView.userTrackingMode = .follow 38 } 39 40 func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { 41 print("検索") 42 43 // キーボードをとじる 44 self.view.endEditing(true) 45 46 // 検索条件を作成 47 let request = MKLocalSearch.Request() 48 request.naturalLanguageQuery = placeSearchBar.text 49 50 // 検索範囲はMKMapViewと同じ 51 request.region = mapView.region 52 53 let localSearch = MKLocalSearch(request: request) 54 localSearch.start(completionHandler: LocalSearchCompHandler(response:error:)) 55 } 56 57 // start(completionHandler:)の引数 58 func LocalSearchCompHandler(response: MKLocalSearch.Response?, error: Error?) -> Void { 59 for searchLocation in (response?.mapItems)! { 60 if error == nil { 61 let searchAnnotation = MKPointAnnotation() 62 // ピンの座標 63 let center = CLLocationCoordinate2DMake(searchLocation.placemark.coordinate.latitude, searchLocation.placemark.coordinate.longitude) 64 searchAnnotation.coordinate = center 65 66 let latStr = center.latitude.description 67 let lonStr = center.longitude.description 68 69 // 配列に検索した位置の緯度と経度をセット 70 searchAnnotationLatArray.append(latStr) 71 searchAnnotationLonArray.append(lonStr) 72 73 // タイトルに場所の名前を表示 74 searchAnnotation.title = searchLocation.placemark.name 75 // ピンを立てる 76 mapView.addAnnotation(searchAnnotation) 77 78 // 配列にピンをセット 79 searchAnnotationArray.append(searchAnnotation) 80 // 配列に場所の名前をセット 81 searchAnnotationTitleArray.append(searchAnnotation.title ?? "") 82 83 } else { 84 print("error") 85 } 86 } 87 } 88 89 func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { 90 print("検索キャンセル") 91 92 // テキストを空にする 93 placeSearchBar.text = "" 94 // キーボードをとじる 95 self.view.endEditing(true) 96 } 97 98 // ピンの詳細設定 99 func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { 100 // 現在地にはピンを立てない 101 if annotation is MKUserLocation { 102 return nil 103 } 104 105 let annotationView = MKPinAnnotationView(annotation: searchAnnotationArray as? MKAnnotation, reuseIdentifier: nil) 106 107 // 吹き出しを表示 108 annotationView.canShowCallout = true 109 110 // 吹き出し内の遷移ボタン 111 let addPlanButton = UIButton() 112 addPlanButton.frame = CGRect(x: 0, y: 0, width: 42, height: 36) 113 addPlanButton.setTitle("遷移", for: .normal) 114 addPlanButton.setTitleColor(.white, for: .normal) 115 addPlanButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 15.0) 116 addPlanButton.layer.backgroundColor = UIColor.orange.cgColor 117 addPlanButton.layer.masksToBounds = true 118 addPlanButton.layer.cornerRadius = 8 119 120 // 吹き出しの右側にボタンをセット 121 annotationView.rightCalloutAccessoryView = addPlanButton 122 123 return annotationView 124 } 125 126 // 吹き出しアクセサリー押下時 127 func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) { 128 // 右側のボタンでReceiveVCに遷移 129 if control == view.rightCalloutAccessoryView { 130 self.performSegue(withIdentifier: "toReceiveVC", sender: nil) 131 } 132 } 133 134 // 遷移時に場所の名前と緯度と経度を渡す 135 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 136 guard let identifier = segue.identifier else { 137 return 138 } 139 140 if identifier == "toReceiveVC" { 141 let receiveVC = segue.destination as! ReceiveViewController 142 receiveVC.place = self.searchAnnotationTitleArray[0] 143 receiveVC.lat = self.searchAnnotationLatArray[0] 144 receiveVC.lon = self.searchAnnotationLonArray[0] 145 } 146 } 147 148}
#####ReceiveTestViewController.swift
不要かもしれませんが、念のため。
Swift
1import UIKit 2 3class ReceiveViewController: UIViewController, UITextFieldDelegate { 4 5 var place: String = "" 6 var lon: String = "" 7 var lat: String = "" 8 @IBOutlet weak var textField: UITextField! 9 @IBOutlet weak var latLabel: UILabel! 10 @IBOutlet weak var lonLabel: UILabel! 11 12 @IBAction func closeButton(_ sender: Any) { 13 self.dismiss(animated: true, completion: nil) 14 } 15 16 override func viewDidLoad() { 17 super.viewDidLoad() 18 // Do any additional setup after loading the view. 19 20 textField.delegate = self 21 22 textField.text = place 23 latLabel.text = "lat : " + lat 24 lonLabel.text = "lon : " + lon 25 } 26 27}
補足情報(FW/ツールのバージョンなど)
Xcode 11.6
Swift 5
ここまで読んでくださり、ありがとうございます。
質問に至らぬ点があるかもしれませんが、どうぞよろしくお願いいたします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。