Codementor Events

GMSMapView Clustering - iOS

Published Oct 09, 2018Last updated Oct 16, 2018
GMSMapView Clustering - iOS

About me

This is my first blog so sorry for the typo and formatting

I am a passionate ios developer from India, having more than 6 + years of experience, my key skills are:

  1. SWIFT
  2. Objective C
  3. Python

Why I wanted to learn GMSMapView Clustering iOS

One of my project has the functionality to show the available hotels/restaurant logo in the map view, But after trying many attempts i learned how to make the clustering with custom markers in GMSMapView.

How I approached learning GMSMapView Clustering iOS

I followed developer.google for all the basic and the tutorials they have provided along with stack overflow discussions etc.

Challenges I faced

I have achieved the simple map clustering by following the developer.google but unable to add the custom icons that I am getting from my API response. So after reading and spending 3-4 hours i have finally done that and i will share this with all of you.

Final thoughts and next steps

// Set up the cluster manager with default icon generator and renderer.
let iconGenerator = GMUDefaultClusterIconGenerator()
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let renderer = GMUDefaultClusterRenderer(mapView: self.mapView, clusterIconGenerator: iconGenerator)
clusterManager = GMUClusterManager(map: self.mapView, algorithm: algorithm, renderer: renderer)
//clusterManager.delegate = self

    // Generate and add random items to the cluster manager.
    generateClusterItems()
    
    // Call cluster() after items have been added to perform the clustering and rendering on map.
    clusterManager.cluster()
  • below function actually creates the cluster objects which I have created in a different class (CustomClusterItem) and adding them to the array and generateClusterItems() function will generate the clustering in the GMSMapView.

private func generateClusterItems() {

    self.markersArray.removeAll()
    
    if (self.results.count) > 0 {
        for i in 0...(self.results.count) - 1 {
            //  let extent = 0.2
            
            let objOffersLocations = self.results[i]
            
            if let lat  = objOffersLocations.latitude  {
                
                kLatitude = Double(lat)!
            }
            
            if let lng  = objOffersLocations.longitude  {
                
                kLongitude = Double(lng)!
            }
            
            if let imageURL = objOffersLocations.initialPhoto?.photo {
                
                let item = CustomClusterItem(position: CLLocationCoordinate2DMake(kLatitude,kLongitude), title: "test", icon: imageURL, location_Id:objOffersLocations.locationId!)
                clusterManager.add(item)
                markersArray.append(item)

            }
            else {
                
                let item = CustomClusterItem(position: CLLocationCoordinate2DMake(kLatitude,kLongitude), title: "test", icon: "", location_Id:objOffersLocations.locationId!)
                clusterManager.add(item)
                markersArray.append(item)
            }
        }
    }
    else {
        let item = CustomClusterItem(position: CLLocationCoordinate2DMake(kLatitude,kLongitude), title: "test", icon: "", location_Id:0)
        clusterManager.add(item)
        markersArray.append(item)
    }
}

Now below is my class for the custom cluster item which accepts the location, id of the object and an iconURL, you can pass whatever information you want at here.

@objc public class CustomClusterItem: NSObject, GMUClusterItem {

public var position: CLLocationCoordinate2D

@objc public var pos_name: String

@objc public var locationId: Int

@objc public var iconURL: String

init(position: CLLocationCoordinate2D, title: String, icon: String, location_Id:Int)
{
    self.position = position
    
    self.pos_name = title
    
    self.iconURL = icon
    
    self.locationId = location_Id
}

}

And now if you want to go into the detail page of any item when user taps on the icon then then GMSMapView delegate will be executed, You can check the below code:

// MARK: - GMUMapViewDelegate

func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
    if let poiItem = marker.userData as? CustomClusterItem {

        let selectedArray = self.results.filter() { $0.locationId == poiItem.locationId }

        if selectedArray.count > 0 {
            
            let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
            let vc = storyboard.instantiateViewController(withIdentifier: "DetailVC") as! DetailVC
            vc.nearbyLocation = selectedArray[0]
            self.navigationController?.pushViewController(vc, animated: true)
        }
    } else {
        NSLog("Did tap a normal marker")
    }
    return false
}

**** Dont forget to add the mapview delegate ***

// Register self to listen to both GMUClusterManagerDelegate and GMSMapViewDelegate events.
clusterManager.setDelegate(self, mapDelegate: self)

Discover and read more posts from Rishi
get started
post commentsBe the first to share your opinion
Rasika Punde
3 years ago

Would you please share GitHub link?

Show more replies