Search code examples
iosswiftcore-datalocationmanager

location in the background does not work


I am developing a code that should get my location every 10 minutes and salvation in CoreData. When I walk into background with conectavo app to xcode can not see the log that the service is running, but when I go out walking the streets he simply not saved or saved too few times.

This is part of my code that should do this function.See save in codeData:

var saveLocationInterval = 60.0

func applicationDidEnterBackground(application: UIApplication) {
        UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler(nil)
        self.timer = NSTimer.scheduledTimerWithTimeInterval(saveLocationInterval, target: self, selector: #selector(AppDelegate.saveLocation), userInfo: nil, repeats: true)
        NSRunLoop.currentRunLoop().addTimer(self.timer, forMode: NSRunLoopCommonModes)

        locationController.startUpdatingLocation()
    }

 func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        saveLocation()
    }

func saveLocation(){
        print("======")
        let logUser = NSEntityDescription.insertNewObjectForEntityForName("LOG_GPS", inManagedObjectContext: self.managedObjectContext) as! LOG_GPS

        if locationController.location == nil{
            logUser.latitude = ""
            logUser.longitude = ""
        } else {
            logUser.latitude = "\(locationController.location!.coordinate.latitude)"
            logUser.longitude = "\(locationController.location!.coordinate.longitude)"
        }

        logUser.velocidade = userSpeed > 0 ? Int(userSpeed) : 0
        logUser.address = "\(userSpeed)"

        if _usuario.chave != nil {
            logUser.chave_usuario = "\(_usuario.chave!)"
        }
        if _empresa.chave != nil {
            logUser.chave_licenca = "\(_empresa.chave!)"
        }

        print("localizaçao salva no bd \(logUser.latitude)")
        let date = NSDate()
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "dd/MM/yy HH:mm:ss"
        let dateString = dateFormatter.stringFromDate(date)
        logUser.data = dateString
        do {
            try self.managedObjectContext.save()
        } catch {
        }
    }

Another major error in my code I can not solve is the User's speed. In the method the low I'm trying to save your speed in a variable and then save the CoreData however this is me always returning a negative value:

func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) {
        var speed: CLLocationSpeed = CLLocationSpeed()
        speed = newLocation.speed
        print(speed * 3.6)
        userSpeed = speed * 3.6
    }

this is my background mode


Solution

  • Possible solution 1

    You need a key in your Info.plist that describes why your app needs background location.

    Go to your Info.plist, find the Bundle Version key and click the + that appears when you hover over that. Then add the key NSLocationAlwaysUsageDescription, set it to be a string, and set the value as whatever you want the description to be, like "We need your location in the background so we share your location with friends."

    Now your app should work. If it doesn't....

    Possible solution 2 (more likely solution if you know what you're doing)

    With iOS 9, Apple made it so that apps on physical devices need a special line of code to run location services in the background. The change was not widely reported on (if at all?) but I managed to figure this one out a while ago. Here's what you need to do to get location services working in the background on physical devices again:

    In your main location tracking view controller's ViewDidLoad put...

    if #available(iOS 9.0, *) {
         locationManager.allowsBackgroundLocationUpdates = true
    } else {
        // You don't need anything else on earlier versions.
    }
    

    This will (mysteriously enough) likely be all you need to solve your problem.