如何在GoogleMaps for iOS中使用Firebase中的标记 [英] How to clustered markers from Firebase in GoogleMaps for iOS

查看:355
本文介绍了如何在GoogleMaps for iOS中使用Firebase中的标记的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个应用程序,我想在地图上显示大量的事件。用户可以点击一个事件,并看到很多关于它的信息。
在另一个视图中,用户可以创建一个新事件,然后将位置和标题存储在Firebase数据库中。
然后,当其他用户在我的应用程序上观看GoogleMaps时,他们可以看到地图上所有标记的事件。
当用户在地图上缩小地图时,我想要将Firebase中的标记聚合在一起,但是由于我在Firebase上加载了数据标记,所以无法工作。
有3个问题:
- 我无法用橙色将我的自定义标记聚集在一起。
- 当地图加载时,标记和集群图标不显示,我需要放大或缩小第一个
- 我想标记的数据显示在infoWindow中,但我必须使用GoogleMap和Firebase上相应标记的正确数据。
- 当我点击一个集群图标时,它也会显示alertController,但是当用户点击一个不在集群图标上的标记时,我只想看到alertController。

<下面是我当前的代码:

pre $ $ $ $ $ $ $ $ $ $ $ $ $ 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()//另一个当前位置
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!

重写func viewDidLoad(){
super.viewDidLoad()
$ b $ locationManager.delegate = self $ b $ 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 $ b $ 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()
}

//下载标记的数据()
func loadMarker(){
ref = Database.database()。reference()
let usersRef = ref.child(markers)
$ b $如果(snapshot.value是NSNull){
print(not found)
} else {$ b())中的usersRef.observeSingleEvent(:.value, $ b为snapshot.children中的孩子{
let userSnap = child as! DataSnapshot
let uid = userSnap.key //每个用户的uid
让userDict = userSnap.value as! [String:AnyObject]
let latitudes = userDict [latitudeEvent] as!双
让经度= userDict [longitudeEvent]为! Double
让bellname = userDict [nom] as!字符串
让belltitre = userDict [titreEvent]为! String
let total = snapshot.childrenCount // Firebase中的标记数量

let positionMarker = CLLocationCoordinate2DMake(纬度,经度)
var diff = Double(round(100 * self。 getDistanceMetresBetweenLocationCoordinates(positionMarker,coord2:self.currentPosition))/ 100)
var dif = Double(round(100 * diff)/ 100)

var positionEvenement = CLLocation(latitude:纬度,经度:longitude)//事件位置

//为了在地址中转换GPS坐标而使用的函数
CLGeocoder()。reverseGeocodeLocation(positionEvenement,completionHandler:{(placemarks,error) - >如果错误!= nil {
print(Reverse geoccoder arencontréune erreur+(error?.localizedDescription)!)
return


if(地标? 。计数)! > 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,经度),名称:)
// self.marker.userData = item //我删除这一行
self.clusterManager.add(item)
self.marker = GMSMarker(position :positionMarker)
self.marker.icon = UIImage(命名为marker-45)
self.marker.title =\(belltitre)
self.marker.snippet = Live de \(bellname)\\\
Lieu:\(adres)\\\
Distance:\(dif)km
self.marker.map = self.maMap
} else {
print(Problèmeavec lesdonnéesreçupar legéocoder)
}
})
}
self.clusterManager.cluster()
func mapView(self,mapDelegate:self)
} _ mapView:GMSMapView,didTap标记:GMSMarker) - > Bool {
如果让poiItem = marker.userData为? POItem {
NSLog(用于群集项目的点击标记\(poiItem.name))
}其他{
NSLog(点击正常标记)
}
return false

$ b $ 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(更新)
返回false
}

func渲染器(_ renderer:GMUClusterRenderer,markerFor object:Any) - > GMSMarker? {
let marker = GMSMarker()
如果let model = object as? POIItem {// POIItem类是你的MarkerModel类
marker.icon = UIImage(命名为:marker-45)//像这样?
//设置gmsmarker的图像视图
}
返回标记
}

2个位置之间的距离
func getDistanceMetresBetweenLocationCoordinates(_ coord1 :CLLocationCoordinate2D,coord2:CLLocationCoordinate2D) - > Double {
let location1 = CLLocation(latitude:coord1.latitude,longitude:coord1.longitude)
let location2 = CLLocation(纬度:coord2.latitude,longitude:coord2.longitude)
var distance =((location1.distance(from:location2))/ 1000)
return bb
$ :AnyObject){
let alertController = UIAlertController(title:,message:,preferredStyle:.actionSheet)
alertController.title = nil
alertController.message = nil
alertController.addAction(UIAlertAction(title:Accéderau live,style:.default,handler:self.accederLive))$ b $ 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)
}

//显示infoWindo w和alertController
func mapView(_ mapView:GMSMapView!,markerInfoWindow marker:GMSMarker!) - > UIView的! {
let infoWindow = Bundle.main.loadNibNamed(InfoWindow,owner:self,options:nil)?如! 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
}


这里是googlemap的截图。



第一个截图是我打开地图,可以看到地图上没有任何东西出现,没有集群图标或隔离标记,这很奇怪。

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

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

  clusterManager = GMUClusterManager(map:maMap,algorithm:algorithm,renderer:renderer)

then

  clusterManager.cluster()
clusterManager.setDelegate(self,mapDelegate:self)



在for循环结束后应放置在 loadMarker()中。 b

您的viewcontroller应符合此协议 GMUClusterManagerDelegate ,然后在viewcontroller中添加这两个方法。

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

let marker = GMSMarker()
如果let model = object as? MarkerModel {
//为gmsmarker
设置图像视图}

返回标记
}

func clusterManager(_ clusterManager:GMUClusterManager,didTap簇:GMUCluster) - > Bool {
let newCamera = GMSCameraPosition.camera(withTarget:cluster.position,zoom:mapView.camera.zoom + 1)
let update = GMSCameraUpdate.setCamera(newCamera)
mapView.moveCamera(更新)
返回false
}

试试这个,其他工作我们会尝试别的。


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.

Here's my current 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) -> 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
}

Sorry it a lil bit long code if you don't understand something let me know, I tried to comment

Here's the screenshot of the googlemap now.

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.

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.

解决方案

Firstly loadMarker() should be called after the clusterManager is initialized i.e

clusterManager = GMUClusterManager(map: maMap, algorithm: algorithm, renderer: renderer)

then

clusterManager.cluster()
clusterManager.setDelegate(self, mapDelegate: self)

should be placed in loadMarker() after for loop ends.

Your viewcontroller should conform to this protocol GMUClusterManagerDelegate then add these 2 methods in viewcontroller.

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
}

Try this and let me know if this works else we will try something else.

这篇关于如何在GoogleMaps for iOS中使用Firebase中的标记的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆