title: How to clustered markers from Firebase in GoogleMaps for iOS
body: <p>I'm developing an app on which I want to show a lot of events on the map. The user can click on an event and see a lot of informations about it.
  In another view, a user can create a new event then the location and title are stored in Firebase database.
  Then when others users watch the GoogleMaps on my app, they are able to see all the events who are a marker in the map.
  I want to cluster the markers from Firebase when the user zoom out on the map but it can't work maybe because of my loaded way of the data markers on Firebase.
  There's 3 issues:
  - I'm not able to cluster my custom marker with orange color.
  - The markers and the clusters icon don't appear when the map load, I need to zoom in or zoom out first
  - I want the data of marker are show in the infoWindow but I got to use the right data for the marker corresponding on the GoogleMap and Firebase.
  - When I click on a cluster icon, it shows the alertController too, but I want only see the alertController when user tap a marker not on the cluster icon.</p>
  
  <p>Here's my current code :</p>
  
  <pre><code>class POIItem: NSObject, GMUClusterItem {
  var position: CLLocationCoordinate2D
  var name: String!
  
  init(position: CLLocationCoordinate2D, name: String) {
      self.position = position
      self.name = name
  }
  }
  
  class NewCarteViewController: UIViewController, GMSMapViewDelegate, CLLocationManagerDelegate, GMUClusterManagerDelegate {
  
  var locationManager = CLLocationManager()
  var positionActuelle = CLLocation() // Another current position
  var currentPosition = CLLocationCoordinate2D()
  var latiti: CLLocationDegrees!
  var longiti: CLLocationDegrees!
  
  private var clusterManager: GMUClusterManager! // Cluster
  private var maMap: GMSMapView!
  var marker = GMSMarker()
  let geoCoder = CLGeocoder()
  
  var ref = DatabaseReference()
  var estTouche: Bool!
  
  override func viewDidLoad() {
      super.viewDidLoad()
  
      locationManager.delegate = self
      locationManager.requestWhenInUseAuthorization()
  
      positionActuelle = locationManager.location!
      latiti = positionActuelle.coordinate.latitude
      longiti = positionActuelle.coordinate.longitude
      currentPosition = CLLocationCoordinate2D(latitude: latiti, longitude: longiti)
  
      let camera = GMSCameraPosition.camera(withTarget: currentPosition, zoom: 10)
      maMap = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
      maMap.mapType = .normal
      maMap.settings.compassButton = true
      maMap.isMyLocationEnabled = true
      maMap.settings.myLocationButton = true
      maMap.delegate = self
      self.view = maMap
  
      let iconGenerator = GMUDefaultClusterIconGenerator()
      let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
      let renderer = GMUDefaultClusterRenderer(mapView: maMap, clusterIconGenerator: iconGenerator)
      clusterManager = GMUClusterManager(map: maMap, algorithm: algorithm, renderer: renderer)
  
      loadMarker()
  }
  
  // Download datas of markers from Firebase Database
  func loadMarker() {
      ref = Database.database().reference()
      let usersRef = ref.child("markers")
  
      usersRef.observeSingleEvent(of: .value, with: { (snapshot) in
          if (snapshot.value is NSNull) {
              print("not found")
          } else {
              for child in snapshot.children {
                  let userSnap = child as! DataSnapshot
                  let uid = userSnap.key // the uid of each user
                  let userDict = userSnap.value as! [String: AnyObject]
                  let latitudes = userDict["latitudeEvent"] as! Double
                  let longitudes = userDict["longitudeEvent"] as! Double
                  let bellname = userDict["nom"] as! String
                  let belltitre = userDict["titreEvent"] as! String
                  let total = snapshot.childrenCount // Number of markers in Firebase
  
                  let positionMarker = CLLocationCoordinate2DMake(latitudes, longitudes)
                  var diff = Double(round(100*self.getDistanceMetresBetweenLocationCoordinates(positionMarker, coord2: self.currentPosition))/100)
                  var dif = Double(round(100*diff)/100)
  
                  var positionEvenement = CLLocation(latitude: latitudes, longitude: longitudes) // Event location
  
                  // Function in order to convert GPS Coordinate in an address
  CLGeocoder().reverseGeocodeLocation(positionEvenement, completionHandler: {(placemarks, error) -&gt; Void in
  
                      if error != nil {
                          print("Reverse geocoder a rencontré une erreur " + (error?.localizedDescription)!)
                          return
                      }
  
                      if (placemarks?.count)! &gt; 0 {
                          print("PlaceMarks \(placemarks?.count)!")
                          let pm = placemarks?[0] as! CLPlacemark
                          var adres = "\(pm.name!), \(pm.postalCode!) \(pm.locality!)"
                          let item = POIItem(position: CLLocationCoordinate2DMake(latitudes, longitudes), name: "")
                          // self.marker.userData = item // I delete this line
                          self.clusterManager.add(item)
                          self.marker = GMSMarker(position: positionMarker)
                          self.marker.icon = UIImage(named: "marker-45")
                          self.marker.title = "\(belltitre)"
                          self.marker.snippet = "Live de \(bellname)\nLieu: \(adres)\nDistance: \(dif) km"
                          self.marker.map = self.maMap
                      } else {
                          print("Problème avec les données reçu par le géocoder")
                      }
                  })
              }
              self.clusterManager.cluster()
              self.clusterManager.setDelegate(self, mapDelegate: self)
          }
      })
  }
  
  func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -&gt; Bool {
      if let poiItem = marker.userData as? POIItem {
          NSLog("Did tap marker for cluster item \(poiItem.name)")
      } else {
          NSLog("Did tap a normal marker")
      }
      return false
  }
  
  func clusterManager(_ clusterManager: GMUClusterManager, didTap cluster: GMUCluster) -&gt; Bool {
      let newCamera = GMSCameraPosition.camera(withTarget: cluster.position, zoom: maMap.camera.zoom + 1)
      let update = GMSCameraUpdate.setCamera(newCamera)
      maMap.moveCamera(update)
      return false
  }
  
  func renderer(_ renderer: GMUClusterRenderer, markerFor object: Any) -&gt; GMSMarker? {
      let marker = GMSMarker()
      if let model = object as? POIItem { // POIItem class is your MarkerModel class
          marker.icon = UIImage(named: "marker-45") // Like this ?
          // set image view for gmsmarker
      }
      return marker
  }
  
  // Distance between 2 locations
  func getDistanceMetresBetweenLocationCoordinates(_ coord1: CLLocationCoordinate2D, coord2: CLLocationCoordinate2D) -&gt; Double {
      let location1 = CLLocation(latitude: coord1.latitude, longitude: coord1.longitude)
      let location2 = CLLocation(latitude: coord2.latitude, longitude: coord2.longitude)
      var distance = ((location1.distance(from: location2)) / 1000)
      return distance
  }
  
  // Affiche les boutons du live
  func alert(_ sender: AnyObject) {
      let alertController = UIAlertController(title: "", message: "", preferredStyle: .actionSheet)
      alertController.title = nil
      alertController.message = nil
      alertController.addAction(UIAlertAction(title: "Accéder au live", style: .default, handler: self.accederLive))
      alertController.addAction(UIAlertAction(title: "Infos event", style: .default, handler: self.infosEvent))
      alertController.addAction(UIAlertAction(title: "Annuler", style: .cancel, handler: nil))
      self.present(alertController, animated: true, completion: nil)
  }
  
  // Display infoWindow and alertController
  func mapView(_ mapView: GMSMapView!, markerInfoWindow marker: GMSMarker!) -&gt; UIView! {
      let infoWindow = Bundle.main.loadNibNamed("InfoWindow", owner: self, options: nil)?.first! as! CustomInfoWindow
      self.estTouche = true
      if self.estTouche == true {
          self.alert(self.estTouche as AnyObject)
      } else {
          print("estTouche est false")
      }
      print(self.estTouche)
      return nil // infoWindow
  }
  </code></pre>
  
  <p>Sorry it a lil bit long code if you don't understand something let me know, I tried to comment</p>
  
  <p>Here's the screenshot of the googlemap now.
  <a href="https://i.stack.imgur.com/VANcE.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/VANcE.png" alt="open map photo"></a>
  <a href="https://i.stack.imgur.com/zwL7G.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/zwL7G.png" alt="after zoom in"></a></p>
  
  <p>The first screenshot is when I open the map, you can see nothing appears on the map, no cluster icon or isolate marker, it strange.</p>
  
  <p>The second screenshot is when I zoom in one time, so after cluster icon appears and one marker appears too.
  What's wrong with my code, I want all cluster icon or marker show when user open the map view.</p>