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

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

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

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

1回答

1728閲覧

MKPointAnnotation配列のうち、選択されているピンのindex番号を取得したい

unagimochimochi

総合スコア7

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2020/08/20 02:40

前提・実現したいこと

MKLocalSearchを利用して、キーワード検索で何個かのピンを立てています。

↓メイン画面(ViewController)
ViewController

このピンは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番目の情報を渡しています。

↓遷移先(ReceiveViewController)
ReceiveViewController

発生している問題

選択されているピンの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

ここまで読んでくださり、ありがとうございます。
質問に至らぬ点があるかもしれませんが、どうぞよろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

自己解決

選択されているピンのindex番号の取得方法はわかりませんでしたが、selectedAnnotationsプロパティを利用して、選択されているピンを新たな配列に格納することで値を渡すことができました。

#####Viewcontroller.swift

Swift

1// 遷移時に場所の名前と緯度と経度を渡す 2override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 3 guard let identifier = segue.identifier else { 4 return 5 } 6 7 if identifier == "toReceiveVC" { 8 let receiveVC = segue.destination as! ReceiveViewController 9 10 // 選択されているピンを新たな配列に格納 11 let selectedSearchAnnotationArray = mapView.selectedAnnotations 12 13 // 選択されているピンは1つのため、0番目を取り出す 14 let selectedSearchAnnotation = selectedSearchAnnotationArray[0] 15 16 // ピンの緯度と経度を取得 17 let latStr = selectedSearchAnnotation.coordinate.latitude.description 18 let lonStr = selectedSearchAnnotation.coordinate.longitude.description 19 20 // 選択されているピンからタイトルを取得 21 if let selectedSearchAnnotationTitle = selectedSearchAnnotation.title { 22 // receiveVCに値を渡す 23 receiveVC.place = selectedSearchAnnotationTitle ?? "" 24 receiveVC.lat = latStr 25 receiveVC.lon = lonStr 26 } 27 } 28}

投稿2020/08/22 03:48

unagimochimochi

総合スコア7

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問