3

I have an iOS application developed in Swift. My app is currently in Swift 2 but I am using Xcode 8 with Swift 3. The app is configured to use the legacy swift language version.

Until recently the app was working correctly.

The app asks for the correct rights for always use the location and the autorisation is correctly set to always.

I renewed the signing identity for the production app and the app stopped to be notified on a location update but was still working in development mode (launched from xcode).

Now I revoked and renew the production and development certificate and the app does not update the location while in background whereas the autorisation is set to always.

The app is correctly installed so I guess that the certificates are okay but I don't understand why the location is not updated in background.

I run the app on an iPhone 7 with IOS 10.2 and xcode automatically manage signing.

Here is my location manager configuration:

public class LocationManager : NSObject, ModuleManager, CLLocationManagerDelegate {

    /// The core location manager
    let coreLocationManager: CLLocationManager

    public var datas: JSONable? {
        get {
            return LocationDatas(locations: self.locations)
        }

        set {
            self.locations = newValue == nil ? [Location]() : newValue as? [Location]
        }
    }

    /// The list of locations to send
    private var locations: [Location]?

    /// The last location
    public var lastLocation: Location? {
        return self.locations?.last
    }

    public override init() {

        self.coreLocationManager = CLLocationManager()
        if #available(iOS 9.0, *) {
            self.coreLocationManager.allowsBackgroundLocationUpdates = true
        }
        // The accuracy of the location data.
        self.coreLocationManager.desiredAccuracy = kCLLocationAccuracyBest;
        // The minimum distance (measured in meters) a device must move horizontally before an update event is generated.
        self.coreLocationManager.distanceFilter = 500; // meters
        self.locations = [Location]()

        super.init()
        self.coreLocationManager.delegate = self
        self.locationManager(self.coreLocationManager, didChangeAuthorizationStatus: CLLocationManager.authorizationStatus())

    }

    // MARK: - CLLocationManager Delegate

    public func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        NSLog("location update")
        guard locations.count > 0 else {
            NSLog("Module Location -- no location available")
            return
        }

        // Add all location waiting in the list to send
        self.locations?.appendContentsOf(locations.map { Location(cllocation: $0) })
        SDKManager.manager?.sendHeartbeat()
    }

    public func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
        switch CLLocationManager.authorizationStatus() {
            case .NotDetermined:
                if #available(iOS 8.0, *) {
                    self.coreLocationManager.requestAlwaysAuthorization()
                } else {
                    self.coreLocationManager.startUpdatingLocation()
                }

            case .Denied, .Restricted:
                NSLog("Module Location -- access denied to use the location")

            case .AuthorizedAlways:
                NSLog("AuthorizedAlways")
                self.coreLocationManager.startUpdatingLocation()
                //self.coreLocationManager.startMonitoringSignificantLocationChanges()

            default:
                break
        }
    }

    public func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        NSLog("Module Location -- error : \(error)")
    }
}

The locationManager function is not called in background.

Here is my info.plist:

enter image description here

Here is the authorization on the phone:

enter image description here

The little location arrow is always there but no location update is logged.

shim
  • 9,289
  • 12
  • 69
  • 108
Florian Courtial
  • 930
  • 1
  • 11
  • 20

2 Answers2

0

I checked your code and it seems to be fine, revise if you have done these required settings

  1. Enable location updates in Background mode
  2. Add NSLocationAlwaysUsageDescription in your info.plist

If you did not do 1st point you app would have crashed but if did not do 2nd point your code will go through but you will never get updates.

Update:

It seems your LocationManager object is released in ARC. Can you try changing your LocationManager class to Singleton by added

static let sharedInstance = LocationManager()

And accessing LocationManager in your code like this

LocationManager.sharedInstance
Matt
  • 1,711
  • 18
  • 20
0

You don't need to use App background Refresh just for Location update in Background. (It can be used for other maintenance work like DB cleaning, uploading, downloading, etc. while charging)

While initializing coreLocationManager, set the following properties as well

// It will allow app running location updates in background state
coreLocationManager.allowsBackgroundLocationUpdates = true 

// It will not pause location automatically, you can set it true if you require it. 
coreLocationManager.pausesLocationUpdatesAutomatically = false 
Nitesh
  • 1,924
  • 21
  • 31