iOS

[Swift]MapViewでクラスタ機能を利用する。

投稿日:2018年12月10日 更新日:

はじめに

こんにちはsuzukiです。本日はSwiftのMapViewのクラスタ機能について触れていこうと思います。 Clusterというライブラリでクラスタリングを行っていたのですが、iOSの11から標準のMapKitでクラスタリングが出来るようになりました。

クラスタリングとは

マップ上の複数のピンを一つにまとめることができます。こちらの機能を利用する事により、マップ上にピンが乱立していると分かりずらかった画面もわかりやすくする事ができます。

PINのクラスタリング機能を利用する

それでは実際にマップとピンを作成していきます。 今回マップはStoryBoardから実装します。

マップの作成

StoryBoard

StoryBoardを利用すればMapViewの配置はとても簡単です。 PINの作成でDelegateの接続が必要になるので、忘れず設定しましょう。

コードから配置したMapに対して指示を出したいのでOutlet接続して起きましょう。一度ビルドを行いMapが全画面で表示されていることを確認して下さい。

PINの作成

それではPINを作成していきます。下記のコードでPinをマップに追加できます。MKPointAnnotationをMapViewにaddAnnotationsで渡しています。

import UIKit
import MapKit
class ViewController: UIViewController,MKMapViewDelegate {
@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 = MKPointAnnotation()
pin1.coordinate = CLLocationCoordinate2D(latitude: 35.44, longitude: 139.64)
pin1.title = "pin1"
let pin2 = MKPointAnnotation()
pin2.coordinate = CLLocationCoordinate2D(latitude: 35.45, longitude: 139.65)
pin2.title = "pin2"
let pin3 = MKPointAnnotation()
pin3.coordinate = CLLocationCoordinate2D(latitude: 35.46, longitude: 139.66)
pin3.title = "pin3"
//作成したPinをマップ上に追加
mapView.addAnnotations([pin1,pin2,pin3])
}
}

ここまで記述してアプリを起動するとPinがマップに追加されているのが確認出来るかと思います。しかしながら、Pinをまとめる機能は動作しておらず、最適な状態とは言えません。クラスタリングを行うためには少しコードを追加しましょう。またPinを装飾するためのカスタムクラスを作成します。

Pinのカスタマイズ

Pinのカスタムを行うためにカスタムクラスを作成します。iOS11から追加されたMKMarkerAnnotationViewを使いやすくするため下記のようなカスタムクラスを作成しました。

 
class CustomPinAnnotation: NSObject, MKAnnotation {
//ID
let clusteringIdentifier : String
//座標
let coordinate: CLLocationCoordinate2D
//Pinのテキスト
let glyphText: String
//Pinのテキストの文字色
let glyphTintColor: UIColor
//Pinの色
let markerTintColor: UIColor
init(_ identifier: String, coordinate: CLLocationCoordinate2D, glyphText: String, glyphTintColor: UIColor = .white, markerTintColor: UIColor) {
self.clusteringIdentifier = identifier
self.coordinate = coordinate
self.glyphText = glyphText
self.glyphTintColor = glyphTintColor
self.markerTintColor = markerTintColor
}
}

カスタムしたPinの利用

ViewDidLoadで記述したPinの追加コードを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("group1",coordinate: CLLocationCoordinate2D(latitude: 35.44, longitude: 139.64), glyphText: "pin1", glyphTintColor: .white, markerTintColor: .black)
let pin2 = CustomPinAnnotation("group1",coordinate: CLLocationCoordinate2D(latitude: 35.45, longitude: 139.65), glyphText: "pin2", glyphTintColor: .white, markerTintColor: .black)
let pin3 = CustomPinAnnotation("group3",coordinate: CLLocationCoordinate2D(latitude: 35.46, longitude: 139.66), glyphText: "pin3", glyphTintColor: .white, markerTintColor: .black)
mapView.addAnnotations([pin1,pin2,pin3])
}

これでカスタムしたPinクラスを使う準備ができました。

CustomPinからMKMarkerAnnotationViewに変換する

それでは最後にmapViewのdelegateでPin情報を取得して置き換えていきましょう。こちらのコードを書いてビルドすると同じclusteringIdentifierを設定しているPinがひとまとまりになっているのが確認できます。

    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
}

こちらのコードでMap上のannotation(CustomPinAnnotation)からMKMarkerAnnotationViewを作成し返却します。個人的にMapKitのコードで解りづらい点として、delegateで渡されるannotationをダウンキャストして、情報を取得する点と、MKAnnotationViewのサブクラスを返却する点です。

  • Pinの情報を持っているクラスは何か
  • 最終的にMap上に配置したいオブジェクトは何か

上記を整理をしながら作成する必要があります。

修正版コード

念のためコードの全部記述いたします。

import UIKit
import MapKit
class ViewController: UIViewController,MKMapViewDelegate {
@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("group1",coordinate: CLLocationCoordinate2D(latitude: 35.44, longitude: 139.64), glyphText: "pin1", glyphTintColor: .white, markerTintColor: .black)
let pin2 = CustomPinAnnotation("group1",coordinate: CLLocationCoordinate2D(latitude: 35.45, longitude: 139.65), glyphText: "pin2", glyphTintColor: .white, markerTintColor: .black)
let pin3 = CustomPinAnnotation("group3",coordinate: CLLocationCoordinate2D(latitude: 35.46, longitude: 139.66), glyphText: "pin3", glyphTintColor: .white, markerTintColor: .black)
mapView.addAnnotations([pin1,pin2,pin3])
}
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
}
}
class CustomPinAnnotation: NSObject, MKAnnotation {
//ID
let clusteringIdentifier : String
//座標
let coordinate: CLLocationCoordinate2D
//Pinのテキスト
let glyphText: String
//Pinのテキストの文字色
let glyphTintColor: UIColor
//Pinの色
let markerTintColor: UIColor
init(_ identifier: String, coordinate: CLLocationCoordinate2D, glyphText: String, glyphTintColor: UIColor = .white, markerTintColor: UIColor) {
self.clusteringIdentifier = identifier
self.coordinate = coordinate
self.glyphText = glyphText
self.glyphTintColor = glyphTintColor
self.markerTintColor = markerTintColor
}
}

さいごに

最後までお付き合い頂き有難うございます。今回の機能は基本的にiOS11からの機能です。もしどうしてもiOS9とかが切れない場合、Clusterというライブラリを使うとPINのクラスタリングができます。以前に使った時は拡張や細かな変更もしやすく大変助かりました。

blog-page_footer_336




blog-page_footer_336




-iOS
-

執筆者:

免責事項

このブログは、記事上部に記載のある投稿日時点の一般的な情報を提供するものであり、投資等の勧誘・法的・税務上の助言を提供するものではありません。仮想通貨の投資・損益計算は複雑であり、個々の取引状況や法律の変更によって異なる可能性があります。ブログに記載された情報は参考程度のものであり、特定の状況に基づいた行動の決定には専門家の助言を求めることをお勧めします。当ブログの情報に基づいた行動に関連して生じた損失やリスクについて、筆者は責任を負いかねます。最新の法律や税務情報を確認し、必要に応じて専門家に相談することをお勧めします。


comment

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

CAPTCHA


関連記事

【Swift】URLスキームのアプリ間連携について

はじめに こんにちは、suzukiです。iOSでアプリ間でデータのやり取りについてまとめました。今回の記事はURLスキームを主に説明いたします。 アプリ間連携とは iOSではアプリ間で情報のやり取りを ...

swift

[Swift]タブの切り替え時にアニメーションが簡単に実装できる「TransitionableTab」

はじめに こんにちは、nukkyです。 今回は、UITabBarControllerの切り替え時にアニメーションを実装できるライブラリ「TransitionableTab」を紹介したいと思います。 & ...

[Swift]AlamofireでファイルのUploadをしてみる

はじめに こんばんは、suzukiです。 今更感がありますが、Alamofireを使って通信周りについてまとめさせていただきます。 最近プロジェクトの修正や追加開発が多く、Carthageでライブラリ ...

【Swift】iOS14 で変わるプライバシー主にIDFA周り

はじめに こんにちはsuzukiです。もうすぐiOS14のリリースがされますね。iOS14の影響を調べる際に、現場で少し問題となったプライバシー周りについて、まとめて行きたいと思います。iOS14のリ ...

Sign in with Appleの実装

はじめに こんにちは、nukkyです。 今回は新しいAppleのサインインシステム「Sign In with Apple」について書いていこうと思います。 Sign in with Appleとは N ...

フォロー

blog-page_side_responsive

2018年12月
日 月 火 水 木 金 土
 1
2345678
9101112131415
16171819202122
23242526272829
3031  

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。