はじめに
こんにちはsuzukiです。 今回は以前に紹介したクラスタ機能とテーブルビューを利用して、クラスタリングされたPINから、どのようなPINが含まれているかをリスト表示をしていこうと思います。 前回の記事はこちらを参照ください。
前回からの修正箇所
前回の記事からコードを少し変更しております。
- enumでカテゴリの定義を追加
- CustomPinAnnotationにカテゴリの追加
- pin2にカテゴリの追記とpin4の作成
- MapViewDelegateの記述場所の変更
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | import UIKit import MapKit class ViewController: UIViewController{ @IBOutlet weak var mapView: MKMapView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. //Mapの中心座標設定 let centerCoordinate = CLLocationCoordinate2D(latitude: 35.444374, longitude: 139.635466) let span = MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2) let centerPosition = MKCoordinateRegion(center: centerCoordinate, span: span) self.mapView.setRegion(centerPosition,animated:true) //PINの追加 let pin1 = CustomPinAnnotation("groupe1",coordinate: CLLocationCoordinate2D(latitude: 35.44, longitude: 139.64), glyphText: "pin1", glyphTintColor: .white, markerTintColor: .black) let pin2 = CustomPinAnnotation("groupe1",category:.busStop,coordinate: CLLocationCoordinate2D(latitude: 35.45, longitude: 139.65), glyphText: "pin2", glyphTintColor: .white, markerTintColor: .black) let pin3 = CustomPinAnnotation("groupe1",coordinate: CLLocationCoordinate2D(latitude: 35.46, longitude: 139.66), glyphText: "pin3", glyphTintColor: .white, markerTintColor: .black) //追加部分 let pin4 = CustomPinAnnotation("groupe1",category:.station,coordinate: CLLocationCoordinate2D(latitude: 35.46, longitude: 139.67), glyphText: "pin4", glyphTintColor: .white, markerTintColor: .black) mapView.addAnnotations([pin1,pin2,pin3,pin4]) } } //MapViewDelegate extension ViewController:MKMapViewDelegate{ func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier, for: annotation) guard let markerAnnotationView = annotationView as? MKMarkerAnnotationView, let annotation = annotation as? CustomPinAnnotation else { return annotationView } markerAnnotationView.clusteringIdentifier = annotation.clusteringIdentifier markerAnnotationView.glyphText = annotation.glyphText markerAnnotationView.glyphTintColor = annotation.glyphTintColor markerAnnotationView.markerTintColor = annotation.markerTintColor return markerAnnotationView } } // カテゴリーの追加 enum PinCategory { case station case busStop case none } //カスタムPINクラス class CustomPinAnnotation: NSObject, MKAnnotation { //ID let clusteringIdentifier : String //カテゴリ let category: PinCategory //座標 let coordinate: CLLocationCoordinate2D //PINのテキスト let glyphText: String //PINのテキストの文字色 let glyphTintColor: UIColor //PINの色 let markerTintColor: UIColor init(_ identifier: String,category:PinCategory = .none , coordinate: CLLocationCoordinate2D, glyphText: String, glyphTintColor: UIColor = .white, markerTintColor: UIColor) { self.clusteringIdentifier = identifier //カテゴリのInput self.category = category self.coordinate = coordinate self.glyphText = glyphText self.glyphTintColor = glyphTintColor self.markerTintColor = markerTintColor } } |
クラスタリングされたPINの内容を取得する
クラスタリングされているPINか判別
今回はPINの内容を取得するため、PINがタップされた時に呼ばれるデリゲートを使用します。
mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView)
上記が呼ばれた時にクラスタリングされているPINか通常のPINか判別します。 クラスタリングされているPINの場合、MKClusterAnnotationにダウンキャストが行えます。
1 2 3 4 5 | func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { if let cluster = view.annotation as? MKClusterAnnotation { //クラスタリングされたPINを選択している } } |
クラスタリングされているPINを取得する
クラスタリングされているPINはMKClusterAnnotationの
memberAnnotations
から取得できます。 memberAnnotationsの型は
[MKAnnotation]
です。カスタマイズされたクラスの情報を取得したい場合はダウンキャストかmapで変換しましょう。
1 2 3 4 5 6 7 8 | func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { if let cluster = view.annotation as? MKClusterAnnotation { //クラスタリングされたPINを選択している guard let pinList = cluster.memberAnnotations as? [CustomPinAnnotation] else{ return } } } |
こちらでクラスタリングされているPINの情報が取得できました。
TableViewとの連携
TableViewをストーリーボードで作成
ストーリーボードでTableViewを実装します。
- TableViewの配置
- デリゲートとデータソースの関連付け
- tableViewとしてIBOutlet接続
- Cellの配置
- Cellという名前でIdentifierを設定
PIN情報の受け取り
PIN情報を受け取るためCustomPinAnnotationの配列を宣言します。
1 2 3 4 5 6 | class ViewController: UIViewController{ @IBOutlet weak var mapView: MKMapView! //tableViewのIBOutlet接続 @IBOutlet weak var tableView: UITableView! //TableView表示のList var selectedPinList:[CustomPinAnnotation] = [] |
selectedPinList
が記述できたら、実際にPIN情報を渡してみましょう。 クラスタリングされているPINを取得するで作成したguard文の後ろに
selectedPinList = pinList
を追加します。
1 2 3 4 5 6 7 | guard let pinList = cluster.memberAnnotations as? [CustomPinAnnotation] else{ return } //pinListを更新 selectedPinList = pinList //次のTableView用のコードが実装できたら下のコードのコメントアウトを外してください。 //reload() |
TableView用のコード
こちらは特に難しいことはないかと思うので今回実装した内容を簡単に記述いたします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | extension ViewController:UITableViewDelegate,UITableViewDataSource{ func reload(){ tableView.reloadData() } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.selectedPinList.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = selectedPinList[indexPath.row].glyphText return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { mapView.showAnnotations([selectedPinList[indexPath.row]], animated: true) } } |
最終コード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | import UIKit import MapKit class ViewController: UIViewController{ @IBOutlet weak var mapView: MKMapView! //tableViewのIBOutlet接続 @IBOutlet weak var tableView: UITableView! //TableView表示のList var selectedPinList:[CustomPinAnnotation] = [] override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. //Mapの中心座標設定 let centerCoordinate = CLLocationCoordinate2D(latitude: 35.444374, longitude: 139.635466) let span = MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2) let centerPosition = MKCoordinateRegion(center: centerCoordinate, span: span) self.mapView.setRegion(centerPosition,animated:true) //PINの追加 let pin1 = CustomPinAnnotation("groupe1",coordinate: CLLocationCoordinate2D(latitude: 35.44, longitude: 139.64), glyphText: "pin1", glyphTintColor: .white, markerTintColor: .black) let pin2 = CustomPinAnnotation("groupe1",category:.busStop,coordinate: CLLocationCoordinate2D(latitude: 35.45, longitude: 139.65), glyphText: "pin2", glyphTintColor: .white, markerTintColor: .black) let pin3 = CustomPinAnnotation("groupe1",coordinate: CLLocationCoordinate2D(latitude: 35.46, longitude: 139.66), glyphText: "pin3", glyphTintColor: .white, markerTintColor: .black) //追加部分 let pin4 = CustomPinAnnotation("groupe1",category:.station,coordinate: CLLocationCoordinate2D(latitude: 35.46, longitude: 139.67), glyphText: "pin4", glyphTintColor: .white, markerTintColor: .black) mapView.addAnnotations([pin1,pin2,pin3,pin4]) //tableviewreload reload() } } //MapViewDelegate extension ViewController:MKMapViewDelegate{ func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier, for: annotation) guard let markerAnnotationView = annotationView as? MKMarkerAnnotationView, let annotation = annotation as? CustomPinAnnotation else { return annotationView } markerAnnotationView.clusteringIdentifier = annotation.clusteringIdentifier markerAnnotationView.glyphText = annotation.glyphText markerAnnotationView.glyphTintColor = annotation.glyphTintColor markerAnnotationView.markerTintColor = annotation.markerTintColor return markerAnnotationView } func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { if let cluster = view.annotation as? MKClusterAnnotation { //クラスタリングされたPINを選択している guard let pinList = cluster.memberAnnotations as? [CustomPinAnnotation] else{ return } //pinListを更新 selectedPinList = pinList reload() } } } extension ViewController:UITableViewDelegate,UITableViewDataSource{ func reload(){ tableView.reloadData() } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.selectedPinList.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = selectedPinList[indexPath.row].glyphText return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { mapView.showAnnotations([selectedPinList[indexPath.row]], animated: true) } } // カテゴリーの追加 enum PinCategory { case station case busStop case none } //カスタムPinクラス class CustomPinAnnotation: NSObject, MKAnnotation { //ID let clusteringIdentifier : String //カテゴリ let category: PinCategory //座標 let coordinate: CLLocationCoordinate2D //PINのテキスト let glyphText: String //PINのテキストの文字色 let glyphTintColor: UIColor //PINの色 let markerTintColor: UIColor init(_ identifier: String,category:PinCategory = .none , coordinate: CLLocationCoordinate2D, glyphText: String, glyphTintColor: UIColor = .white, markerTintColor: UIColor) { self.clusteringIdentifier = identifier //カテゴリのInput self.category = category self.coordinate = coordinate self.glyphText = glyphText self.glyphTintColor = glyphTintColor self.markerTintColor = markerTintColor } } |
さいごに
最後までありがとうございます。テーブルビューの表示非表示を切り替えたり、普通のピンをタップしたときの処理を追加したり等アプリとしてリリースする迄には実装したい内容はたくさんありますが、今回の記事はここまでとさせていただきます。また機会があれば内容を充実させて行きます。