Search code examples
swiftgoogle-mapsgoogle-maps-markersmarkerclusterer

Google Map with Cluster and Custom view marker lagging too much while zoomIn and zoomOut


I want to load GoogleMap with custom view in replace of GMSMarker and want to show clustering and I have done that. But I'm facing lagging & memory usage while zoomIn or ZoomOut the Map.

I have load custom view to GMSMarker infoView

Here is my code.

class InitialMapViewController: UIViewController, GMUClusterManagerDelegate, GMUClusterRendererDelegate {

    private var clusterManager: GMUClusterManager!
    @IBOutlet weak var mapView: GMSMapView!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.initializeClusterItems()
        self. setMapView()
    }

    //MARK:- Map view actions
        func setMapView() {
            mapView.delegate = self
            mapView.isMyLocationEnabled = true
            mapView.settings.myLocationButton = true
            mapView.padding = UIEdgeInsets(top: 0, left: 0, bottom: 50, right: 0)
            mapView.mapType = .normal

            self.mapView.camera = self.defaultCamera(latitude: SharedData.sharedInstance.userLocation.coordinate.latitude, longitude: SharedData.sharedInstance.userLocation.coordinate.longitude)
        }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.getAllFriendsList()
    }

    //MARK: INITIALIZE CLUSTER ITEMS
    func initializeClusterItems() {
        let iconGenerator = GMUDefaultClusterIconGenerator()
        let algorithm = GMUGridBasedClusterAlgorithm()
        let renderer = GMUDefaultClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator)
        renderer.delegate = self
        self.clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)
    }

    func renderer(_ renderer: GMUClusterRenderer, willRenderMarker marker: GMSMarker) {
        guard let _ = marker.userData as? POIItem else { return }

        if UIImage(named: "profile_circle_gradiant") != nil {
            marker.iconView = UIImageView(image: nil, highlightedImage: nil)
        }
    }

    private func clusterManager(clusterManager: GMUClusterManager, didTapCluster cluster: GMUCluster) {
    }

    func defaultCamera(latitude: Double, longitude: Double) -> GMSCameraPosition {
        let camera = GMSCameraPosition.camera(withLatitude: latitude,
                                              longitude: longitude,
                                              zoom: 16)
        return camera
    }

    func setMarkers() {
        for i in 0..<SharedData.sharedInstance.allFriends.count {
            let marker = GMSMarker()
            let friend = SharedData.sharedInstance.allFriends[i]
            marker.position = CLLocationCoordinate2D.init(latitude: friend.user_details.latitude , longitude: friend.user_details.longitude)
            //marker.icon = imgTypeDoctor
            marker.accessibilityHint = String(i)

            let infoWindow = Bundle.main.loadNibNamed("HomeMapInfoView", owner: self, options: nil)?.first as! HomeMapInfoView
            //infoWindow.imgUser.sd_setImage(with: URL(string: friend.user_details.user_photo), placeholderImage: #imageLiteral(resourceName: "User_profile"), options: .highPriority, completed: nil)
            infoWindow.imgCar.image = UIImage.init(named: "small_" + friend.user_details.car_personality_name)
            infoWindow.imgCar1.image = UIImage.init(named: "small_" + friend.user_details.car_personality_name)
//            infoWindow.lblName.text = friend.user_details.name
//            infoWindow.lblUsername.text = "@" + friend.user_details.screen_name

            //KULDEEP 01/03/2019
            infoWindow.btnImgVW.tag = Int(marker.accessibilityHint!) ?? 0
            infoWindow.isUserInteractionEnabled = false
            infoWindow.btnImgVW.addTarget(self, action: #selector(btnUserTapped(_:)), for: .touchUpInside)
            marker.iconView = infoWindow
            marker.tracksViewChanges = true

            //marker.userData = friend
            marker.map = mapView
            //mapView.selectedMarker = marker
            //print(i)
            self.generatePOIItems(String(format: "%d", i), position: marker.position, icon: nil)
        }
        self.clusterManager.cluster()
        //self.clusterManager.setDelegate(self, mapDelegate: self)
    }

    func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) {
        UIView.animate(withDuration: 5.0, animations: { () -> Void in
            //self.londonView?.tintColor = .blue
        }, completion: {(finished) in
            // Stop tracking view changes to allow CPU to idle.
            //mapView.selectedMarker?.tracksViewChanges = false
        })
    }

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

        let marker = GMSMarker()
        if object is POIItem {
            // set image view for gmsmarker

        }

        return marker
    }

    func generatePOIItems(_ accessibilityLabel: String, position: CLLocationCoordinate2D, icon: UIImage?) {

        let item = POIItem(position: position, name: accessibilityLabel)
        self.clusterManager.add(item)
    }
}

Please guide me why map is lagging when I zoomIn or zoomOut the Map or what am I missing on this code?


Solution

  • Here I fix the map lagging issue and for that I have done the following things.

    • Instead of loading all marker iconView at the starting, I load it inside willRenderMarker so it initially load the 1 or 2 marker iconView and when I zoomin the map clustering expand and marker iconView displays.

    Here is the working code.

    class InitialMapViewController: UIViewController, GMUClusterManagerDelegate, GMUClusterRendererDelegate {
    
        private var clusterManager: GMUClusterManager!
        @IBOutlet weak var mapView: GMSMapView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.initializeClusterItems()
            self. setMapView()
        }
    
        //MARK:- Map view actions
            func setMapView() {
                mapView.delegate = self
                mapView.isMyLocationEnabled = true
                mapView.settings.myLocationButton = true
                mapView.padding = UIEdgeInsets(top: 0, left: 0, bottom: 50, right: 0)
                mapView.mapType = .normal
    
                self.mapView.camera = self.defaultCamera(latitude: SharedData.sharedInstance.userLocation.coordinate.latitude, longitude: SharedData.sharedInstance.userLocation.coordinate.longitude)
            }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            self.getAllFriendsList()
        }
    
        //MARK: INITIALIZE CLUSTER ITEMS
        func initializeClusterItems() {
            let iconGenerator = GMUDefaultClusterIconGenerator()
            let algorithm = GMUGridBasedClusterAlgorithm()
            let renderer = GMUDefaultClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator)
            renderer.delegate = self
            self.clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)
        }
    
        func renderer(_ renderer: GMUClusterRenderer, willRenderMarker marker: GMSMarker) {
            marker.groundAnchor = CGPoint(x: 0.5, y: 1)
            if let markerData = (marker.userData as? POIItem) {
                let infoWindow = Bundle.main.loadNibNamed("InitialMapInfoView", owner: self, options: nil)?.first as! InitialMapInfoView
                infoWindow.imgUser.sd_setImage(with: URL(string: markerData.friend.user_details.user_photo_small), placeholderImage: #imageLiteral(resourceName: "User_profile"), options: .highPriority, completed: nil)
                infoWindow.imgCar.image = UIImage.init(named: "small_" + markerData.friend.user_details.car_personality_name)
                infoWindow.lblName.text = markerData.friend.user_details.name
                infoWindow.btnImgVW.tag = markerData.userIndex
                infoWindow.btnImgVW.addTarget(self, action: #selector(btnUserTapped(_:)), for: .touchUpInside)
                marker.accessibilityHint = String(markerData.userIndex)
                marker.iconView = infoWindow
                marker.tracksViewChanges = false
            }
        }
    
        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
        }
    
        func defaultCamera(latitude: Double, longitude: Double) -> GMSCameraPosition {
            let camera = GMSCameraPosition.camera(withLatitude: latitude,
                                                  longitude: longitude,
                                                  zoom: 16)
            return camera
        }
    
        func setMarkers() {
            for i in 0..<SharedData.sharedInstance.allFriends.count {
                let marker = GMSMarker()
                let friend = SharedData.sharedInstance.allFriends[i]
                marker.position = CLLocationCoordinate2D.init(latitude: friend.user_details.latitude , longitude: friend.user_details.longitude)
                marker.accessibilityHint = String(i)
                marker.icon = nil
                marker.tracksViewChanges = true
               marker.map = mapView
                self.generatePOIItems(String(format: "%d", i), position: marker.position, icon: nil, friend: friend, userIndex: i)
            }
            clusterManager.cluster()
            clusterManager.setDelegate(self, mapDelegate: self)
        }
    
        func generatePOIItems(_ accessibilityLabel: String, position: CLLocationCoordinate2D, icon: UIImage?) {
    
            let item = POIItem(position: position, name: accessibilityLabel)
            self.clusterManager.add(item)
        }
    
        func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
            if marker.accessibilityHint != nil {
                let friend = SharedData.sharedInstance.allFriends[Int(marker.accessibilityHint!) ?? 0]
                objSelectedUser = friend
                self.setUserData(friend: objSelectedUser)
                self.showUserLatestBeeppView()
            }
            return true
        }
    }