mapbox-maps-ios icon indicating copy to clipboard operation
mapbox-maps-ios copied to clipboard

Disabling Location Service for map view not working

Open SigmaAppdevelopment opened this issue 7 months ago • 4 comments

Environment

  • Xcode version: 16.3
  • iOS version: 18.0
  • Maps SDK Version: 11.12.2

Observed behavior and steps to reproduce

When moving app to background, we want to stop location updates to save energy. on previous versions this worked:

locationProvider.removeLocationObserver(for: self) mapView.location.options.puckType = .none

Now this has no effect, the app is still requesting location updates.

Is there a workaround?

SigmaAppdevelopment avatar Jun 06 '25 12:06 SigmaAppdevelopment

Hi @SigmaAppdevelopment, are you using our default LocationProvider or are you using your own? We have deprecated LocationManager/locationProvider in favor of onLocationChange; if you are accessing locationProvider it will return nil, so if your provided code is after some guard expression i.e guard let locationProvider = mapView.location.locationProvider then it probably would take no effect

can you provide a bit more elaborated snippet on how you setup the map, how you're observing/unobserving location updates?

maios avatar Jun 09 '25 12:06 maios

Hi here is our code

import Foundation import MapboxMaps import CoreLocation import UIKit

protocol CameraLocationConsumerDelegate: AnyObject { func onLocationUpdate(location: CLLocationCoordinate2D) }

// Create class which conforms to LocationConsumer, update the camera's centerCoordinate when a locationUpdate is received class CameraLocationConsumer: LocationObserver {

public typealias Completion = (Bool) -> ()

weak var mapView: MapView?
weak var delegate: CameraLocationConsumerDelegate? = nil

// A location provider that you use to customize location settings.
let locationProvider = AppleLocationProvider()

// initiale Location sofort setzen (keine Animation)
var animateLocationUpdates = false
var isUpdatingLocation = false
var followLocationUpdates = true
var ownerStr: String = ""

/// App hat LocationUpdates gestartet
private var locationUpdatesRequired = true

init(mapView: MapView, owner: String) {
    self.ownerStr = owner
    self.mapView = mapView
    
    locationProvider.options.activityType = .fitness
    locationProvider.options.desiredAccuracy = kCLLocationAccuracyBest
    locationProvider.options.distanceFilter = CLLocationDistance(2)
    self.mapView?.location.options.puckBearingEnabled = false // eingene Logik (rotation nur, wenn Distanz zw. Locations > 5 m)
    
    // Override the default location provider with the custom one.
    mapView.location.override(provider: locationProvider)
    
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(appMovedToBackground),
                                           name: UIApplication.willResignActiveNotification,
                                           object: nil)
    
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(appMovedToForeground),
                                           name: UIApplication.didBecomeActiveNotification,
                                           object: nil)
}

func checkPermission(completion: @escaping Completion) {
    DispatchQueue.global(qos: .userInitiated).async {
        var hasPermission = false
        if CLLocationManager.locationServicesEnabled() {
            let manager = CLLocationManager()
            switch manager.authorizationStatus {
                case .notDetermined, .restricted, .denied:
                hasPermission = false
                case .authorizedAlways, .authorizedWhenInUse:
                hasPermission = true
                @unknown default:
                hasPermission = false
            }
        }
        DispatchQueue.main.async {
            completion(hasPermission)
        }
    }
}

private func askForPermission() {
    // For use in foreground
    CLLocationManager().requestWhenInUseAuthorization()
}

func startLocationUpdates() {
    self.locationUpdatesRequired = true
    
    checkPermission(completion: { [weak self] hasPermission in
        guard let self = self else { return }
        
        if !hasPermission {
            self.askForPermission()
        } else {
            if !self.isUpdatingLocation {
                print("startLocationUpdates, \(self.ownerStr)")
                // Register the location consumer with the map
                // Note that the location manager holds weak references to consumers, which should be retained
                locationProvider.addLocationObserver(for: self)
                self.isUpdatingLocation = true
            }
            self.setPuckType()
        }
    })
}

/**
 * @param auto: LocationUpdates werden gestoppt, wenn App in Hintergrund gelegt wird, und wieder gestartet, wenn App in Vordergrund
 */
func stopLocationUpdates(auto: Bool = false) {
    if !auto {
        self.locationUpdatesRequired = false
    }
    
    if isUpdatingLocation {
        print("stopLocationUpdates, \(ownerStr)")
        locationProvider.removeLocationObserver(for: self)
        isUpdatingLocation = false
        self.setPuckType()
    }
}

func onLocationUpdateReceived(for locations: [Location]) {       
    delegate?.onLocationUpdate(location: newLocation.coordinate)
}

func setPuckType() {
    if isUpdatingLocation {
        if mapView?.location.options.puckType != .puck2D() {
            let topImage = UIImage(named: "location-dot-inner")
            let shadowImage = UIImage(named: "location-dot-outer")
			let pulsing = Puck2DConfiguration.Pulsing(color: UIColor(named: "sigma_red")!, radius: .constant(30.0))
			let puckConfig = Puck2DConfiguration(topImage: topImage, shadowImage: shadowImage, scale: .constant(0.8), pulsing: pulsing, showsAccuracyRing: false)

            mapView?.location.options.puckType = .puck2D(puckConfig)
        }
    } else {
        if mapView?.location.options.puckType != .none {
            mapView?.location.options.puckType = .none
        }
    }
}

@objc func appMovedToBackground() {
    stopLocationUpdates(auto: true)
}

@objc func appMovedToForeground() {
    if locationUpdatesRequired {
        startLocationUpdates()
    }
}

}

SigmaAppdevelopment avatar Jun 10 '25 07:06 SigmaAppdevelopment

By the way, can I disable telemetry? https://www.mapbox.com/telemetry

I only want to show static data, so there should be no location access. except one view, this has location access, so that's the reason location permission is set.

SigmaAppdevelopment avatar Jun 10 '25 08:06 SigmaAppdevelopment

I also encountered the same problem. Can anyone tell me how to disable Mapbox positioning?

pkuoliver avatar Aug 02 '25 09:08 pkuoliver