What I am trying to accomplish is to refresh the map every X seconds. When doing so, I want to update the content of info window of selected marker. However, the marker data is updated (tried with lat/lng), but the info window data stays the same. How can I update the info window data, without having to recreate it?
If I always recreate the info window (re-select the marker), the info window content changes, but user experience is awful, as info window is blinking.
The code for updating marker data
private func updateMarker(index: Int, markerData: MarkerData, select: Bool) {
markersOnMap[index].title = markerData.time.description
if markersOnMap[index].hasChangedPosition(markerData: markerData) {
markersOnMap[index].position = markerData.getPosition()
UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
}
//Info window is recreated, but the UI is awful
//if select {
//mapView?.selectedMarker = nil
//mapView?.selectedMarker = markersOnMap[index]
//}
}
Code to create the marker and add it to the map:
private func addMarker(markerData: MarkerData, select: Bool) {
let marker = GMSMarker()
marker.map = mapView
marker.position = markerData.getPosition()
marker.userData = markerData.tranId
marker.title = markerData.time.description
marker.groundAnchor = CGPoint(x: 0.5, y: 0.5)
if select == true {
//Where markerInfoWindow is created
marker.icon = UIImage(named: MyImages.markerIcon)
marker.tracksInfoWindowChanges = true
mapView?.selectedMarker = marker
} else {
marker.iconView = getMyIconView(posTime: markerData.time)
}
markersOnMap.append(marker)
}
Info window creation
func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? {
let posTime = CLong(marker.title ?? "0") ?? 0
var rect = CGRect(x: 0, y: 0, width: 150, height: 140)
let hostingController = UIHostingController(rootView: MyInfoView(device: device, posTime: posTime))
hostingController.view.frame = rect
hostingController.view.backgroundColor = .clear
return hostingController.view
}
Since it was not possible to accomplish the desired behaviour with marker update, I compromised with the hostingController. I converted it into local variable, which is initialized once the marker info window is created. Every time I want to update the info window data, I use the instance of hosting controller to do so.
Init the hostingController
func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? {
let posTime = CLong(marker.title ?? "0") ?? 0
hostingController = UIHostingController(rootView: MyInfoView(device: device, posTime: posTime))
hostingController?.view.frame = CGRect(x: 0, y: 0, width: 150, height: 140)
hostingController?.view.backgroundColor = .clear
return hostingController?.view
}
Update info window data (posTime in this case)
private func updateMarker(index: Int, markerData: MarkerData, select: Bool) {
markersOnMap[index].title = markerData.time.description
if markersOnMap[index].hasChangedPosition(markerData: markerData) {
markersOnMap[index].position = markerData.getPosition()
UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
}
if select {
hostingController?.rootView.posTime = markerData.time
}
}