Developer's Blog

iOS11 アノテーション クラスタリング

こんにちは、アプリケーション共同開発部の大江です。
2017年の9月に発表されたiOS11ではiPhoneXの登場に伴うSafe Areaの導入など開発者にとって大きな変化がありました。 あまり注目を浴びていませんが、iOS11ではMapKitも大幅に改良されました。 その中でも注目すべきは、これまではClusterClusterKitなどのライブラリに頼ることが多かったアノテーションのクラスタリングがMapKitの機能として公式に追加されたことです。 そこで、今回はMapKitでアノテーションをクラスタリングする方法について紹介します。

実装方法

このサンプルコードではフェンリルの4つの所在地にアノテーションを配置します。

class FenrirOfficeAnnotation: NSObject, MKAnnotation {

    static let clusteringIdentifier = "FenrirOffice"

    let coordinate: CLLocationCoordinate2D

    let glyphText: String

    let glyphTintColor: UIColor

    let markerTintColor: UIColor

    init(_ coordinate: CLLocationCoordinate2D, glyphText: String, glyphTintColor: UIColor, markerTintColor: UIColor) {
        self.coordinate = coordinate
        self.glyphText = glyphText
        self.glyphTintColor = glyphTintColor
        self.markerTintColor = markerTintColor
    }

}

class ViewController: UIViewController, MKMapViewDelegate {

    @IBOutlet weak var mapView: MKMapView!

    override func viewDidLoad() {
        super.viewDidLoad()

        mapView.delegate = self

        let osaka = FenrirOfficeAnnotation(CLLocationCoordinate2D(latitude: 34.705563, longitude: 135.494851), glyphText: "大阪本社", glyphTintColor: .white, markerTintColor: .red)
        let tokyo = FenrirOfficeAnnotation(CLLocationCoordinate2D(latitude: 35.625018, longitude: 139.721239), glyphText: "東京支社", glyphTintColor: .white, markerTintColor: .magenta)
        let nagoya = FenrirOfficeAnnotation(CLLocationCoordinate2D(latitude: 35.174341, longitude: 136.912334), glyphText: "名古屋支社", glyphTintColor: .white, markerTintColor: .orange)
        let shimane = FenrirOfficeAnnotation(CLLocationCoordinate2D(latitude: 35.474979, longitude: 133.067409), glyphText: "島根支社", glyphTintColor: .brown, markerTintColor: .yellow)

        let annotations = [osaka, tokyo, nagoya, shimane]
        mapView.addAnnotations(annotations)

    }

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {

        let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier, for: annotation)

        guard let markerAnnotationView = annotationView as? MKMarkerAnnotationView,
            let fenrirOfficeAnnotation = annotation as? FenrirOfficeAnnotation else { return annotationView }

        markerAnnotationView.clusteringIdentifier = FenrirOfficeAnnotation.clusteringIdentifier
        markerAnnotationView.glyphText = fenrirOfficeAnnotation.glyphText
        markerAnnotationView.glyphTintColor = fenrirOfficeAnnotation.glyphTintColor
        markerAnnotationView.markerTintColor = fenrirOfficeAnnotation.markerTintColor

        return markerAnnotationView
    }

}

このように、MKAnnotationView.clusteringIdentifierに任意の文字列を設定するだけで、MKAnnotationViewが自動でクラスタリングされるようになります。

実行結果

マップのズームレベルを変更すると、以下のGIFアニメーションのようにアノテーションが自動でクラスタリングされます。

補足

clusteringIdentifier

MKAnnotationViewのオブジェクト毎にclusteringIdentifierを設定することができますが、clusteringIdentifierの値が異なるMKAnnotationViewはクラスタリングされません。

MKAnnotationView.clusteringIdentifierのデフォルト値は`nil`であり、clusteringIdentifierの値が`nil`であるMKAnnotationViewはクラスタリングの対象にはなりません。

MKMarkerAnnotationView

iOS11で登場したMKAnnotationViewのサブクラスです。

iOS11からはMKMapViewにMKMarkerAnnotationViewがデフォルトで登録されています。

このため、MKMapView.register(\_:forAnnotationViewWithReuseIdentifier:)を行わなくとも、MKMapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier, for: annotation)でMKMarkerAnnotationViewを取得できます。

MKMarkerAnnotationViewは、任意の文字や画像を表示できるglyphTextやglyphImage、アノテーションの色を変更できるmarkerTintColorなどのプロパティが用意されており、デザインを柔軟にカスタマイズすることができます。

まとめ

iOS11でMapKit標準機能となったアノテーションのクラスタリングについて紹介しました。

是非一度試してみてください。

参考

What’s New in MapKit

フェンリルの Facebook ページでは、最新トピックをお知らせしています。よろしければいいね!してください!

Copyright © 2019 Fenrir Inc. All rights reserved.