如何在 iOS 版 GoogleMaps 中从 Firebase 聚集标记

0 google-maps markerclusterer ios firebase swift

我正在开发一个应用程序,我想在该应用程序上在地图上显示很多事件。用户可以单击一个事件并查看有关它的大量信息。在另一个视图中,用户可以创建一个新事件,然后将位置和标题存储在 Firebase 数据库中。然后当其他用户在我的应用程序上观看 GoogleMaps 时,他们能够看到在地图中作为标记的所有事件。当用户在地图上缩小时,我想从 Firebase 中聚类标记,但它无法工作,可能是因为我在 Firebase 上加载数据标记的方式。有 3 个问题: - 我无法将我的自定义标记与橙色聚集在一起。- 地图加载时不会出现标记和集群图标,我需要先放大或缩小 - 我希望标记的数据显示在信息窗口中,但我必须为 GoogleMap 和 Firebase 上对应的标记使用正确的数据。- 当我点击集群图标时,它也会显示 alertController,但我只想在用户点击不在集群图标上的标记时看到 alertController。

这是我当前的代码:

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) -> Void in

                    if error != nil {
                        print("Reverse geocoder a rencontré une erreur " + (error?.localizedDescription)!)
                        return
                    }

                    if (placemarks?.count)! > 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) -> 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) -> 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) -> 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) -> 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!) -> 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
}
Run Code Online (Sandbox Code Playgroud)

对不起,代码有点长,如果你不明白让我知道,我试着评论

这是现在googlemap的屏幕截图。 打开地图照片 放大后

第一个截图是当我打开地图时,你可以看到地图上什么都没有出现,没有集群图标或隔离标记,很奇怪。

第二张截图是当我放大一次时,所以在出现集群图标后也出现一个标记。我的代码有什么问题,我希望在用户打开地图视图时显示所有集群图标或标记。

Pra*_*ney 5

首先loadMarker()应该在 clusterManager 初始化后调用,即

clusterManager = GMUClusterManager(map: maMap, algorithm: algorithm, renderer: renderer)
Run Code Online (Sandbox Code Playgroud)

然后

clusterManager.cluster()
clusterManager.setDelegate(self, mapDelegate: self)
Run Code Online (Sandbox Code Playgroud)

应该放在loadMarker()for 循环结束之后。

您的视图控制器应符合此协议,GMUClusterManagerDelegate然后在视图控制器中添加这 2 个方法。

func renderer(_ renderer: GMUClusterRenderer, markerFor object: Any) -> GMSMarker? {

    let marker = GMSMarker()
    if let model = object as? MarkerModel {
         // set image view for gmsmarker
    }

    return marker
}

func clusterManager(_ clusterManager: GMUClusterManager, didTap cluster: GMUCluster) -> Bool {
    let newCamera = GMSCameraPosition.camera(withTarget: cluster.position, zoom: mapView.camera.zoom + 1)
    let update = GMSCameraUpdate.setCamera(newCamera)
    mapView.moveCamera(update)
    return false
}
Run Code Online (Sandbox Code Playgroud)

试试这个,让我知道这是否有效,否则我们将尝试其他方法。