Swiftui Google Maps user marker in top left corner issue

Viewed 218

When I open the map, the user's marker is in the upper left corner, instead of being in the center, just when I click show my position button, the camera becomes so that the user marker is in the upper left corner again. What is the problem ? how do i show the user marker in the center of the map. map screen

My LocationManager class:

class LocationManager: NSObject, ObservableObject {
    
    // Singleton instance
    public static let shared : LocationManager = {
        return LocationManager()
    }()
    
    private let locationManager = CLLocationManager()
    
    @Published var location: CLLocation = CLLocation(latitude: 0.0, longitude: 0.0)
    
    override init() {
        super.init()
        
        locationManager.delegate = self
        locationManager.allowsBackgroundLocationUpdates = true
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.startUpdatingLocation()
        locationManager.requestWhenInUseAuthorization()
    
        location = locationManager.location  ?? CLLocation(latitude: 0.0, longitude: 0.0)
    }
    
}

extension LocationManager: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let currentLocation = locations.last else { return }
        self.location = currentLocation
    }
    
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if status == .authorizedWhenInUse {
            locationManager.requestLocation()
            location = locationManager.location ?? CLLocation(latitude: 0.0, longitude: 0.0)
        }
    }
    
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Swift.Error) {
        appLog.debug(error)
    }
}

MapView:

struct GoogleMapView: UIViewRepresentable {
    
    @Binding var coordinates: [Coordinate]
    
    let zoom: Float = 15.0
    var showMyLocationButton = true
    var mapBoundsCallback: ([Double], [Double]) -> ()
    
    private var cancellables = Set<AnyCancellable>()
    private var mapView: GMSMapView?
    
    init(coordinates: Binding<[Coordinate]>,
         zoom: Float = 15.0,
         showMyLocationButton: Bool = true,
         mapBoundsCallback: @escaping ([Double], [Double]) -> ()) {
        
        self.showMyLocationButton = showMyLocationButton
        self.mapBoundsCallback = mapBoundsCallback
        _coordinates = coordinates
    }
    
    func makeUIView(context: Self.Context) -> GMSMapView {
        let camera = GMSCameraPosition.camera(withTarget: LocationManager.shared.location.coordinate , zoom: zoom)
        let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
        mapView.animate(to: camera)
        mapView.delegate = context.coordinator
        mapView.settings.compassButton = true
        mapView.isMyLocationEnabled = true
        mapView.settings.myLocationButton = showMyLocationButton
        return mapView
    }
    
    func updateUIView(_ mapView: GMSMapView, context: Context) {
        mapView.clear()
        
        if coordinates.isEmpty {
            return
        }
        
        let path = GMSMutablePath()
        var bounds = GMSCoordinateBounds()
        
        for coordinate in coordinates {
            if let lat = coordinate.coordinates?[0], let lng = coordinate.coordinates?[1] {
                let locationCoordinate = CLLocationCoordinate2DMake(lat, lng)
                path.add(locationCoordinate)
                bounds = bounds.includingCoordinate(locationCoordinate)
            }
        }
        
        let rectangle = GMSPolyline(path: path)
        rectangle.strokeColor = Theme.colorDarkGrey.uiColor()
        rectangle.strokeWidth = 2.0
        rectangle.map = mapView
        
        mapView.animate(with: GMSCameraUpdate.fit(bounds))
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator { ne, sw in
            mapBoundsCallback(ne, sw)
        }
    }
    
    class Coordinator: NSObject, GMSMapViewDelegate {
        
        var cameraPositionCallback: ([Double], [Double]) -> ()
        
        init(cameraPositionCallback: @escaping ([Double], [Double]) -> ()) {
            self.cameraPositionCallback = cameraPositionCallback
        }
        
        func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) {
            let farRight = mapView.projection.visibleRegion().farRight
            let nearLeft = mapView.projection.visibleRegion().nearLeft
            let ne: [Double] = [Double(farRight.latitude), Double(farRight.longitude)]
            let sw: [Double] = [Double(nearLeft.latitude), Double(nearLeft.longitude)]
            cameraPositionCallback(ne, sw)
        }
    }
}
1 Answers

I found that issue happens only on views opens by NavigationLink. If store GMSMapView() on some root ViewModel, present GoogleMapView on some first view as first layer, then you can pass GMSMapView() to other views, build GoogleMapView and present it. For me such solution helps...

Related