4

I have the following code to get location updates (iOS 7):

import UIKit
import CoreLocation

class FirstViewController: UIViewController, CLLocationManagerDelegate {

    var locationManager: CLLocationManager!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @IBAction func startTracking(sender : AnyObject) {
        NSLog("Start tracking")
        if (locationManager == nil) {
            locationManager = CLLocationManager()
            locationManager.delegate = self
            locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
            locationManager.distanceFilter = kCLDistanceFilterNone
            locationManager.pausesLocationUpdatesAutomatically = false
        }

        locationManager.startUpdatingLocation()
    }

    @IBAction func stopTracking(sender : AnyObject) {
        NSLog("Stop tracking")
        stopUpdatingLocation()
    }

    func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
        NSLog("Error" + error.description)
    }

    func locationManager(manager:CLLocationManager, didUpdateLocations locations:AnyObject[]) {
        println("locations = \(locations)")
    }

    func locationManager(manager: CLLocationManager!,
        didChangeAuthorizationStatus status: CLAuthorizationStatus) {

        switch status {
            case CLAuthorizationStatus.Restricted:
                locationStatus = "Access: Restricted"
                break
            case CLAuthorizationStatus.Denied:
                locationStatus = "Access: Denied"
                break
            case CLAuthorizationStatus.NotDetermined:
                locationStatus = "Access: NotDetermined"
                shouldIAllow = true
                break
            default:
                locationStatus = "Access: Allowed"
                shouldIAllow = true
        }
        NSLog(locationStatus)
    }
}

I get only one update in the didUpdateLocations: after calling startTracking the didUpdateLocations will be called only once and in 5 seconds GPS indicator disappears.

Some details:

  • application is authorized to use location services
  • application is in foreground
  • interestingly enough: if I put breakpoint in the didUpdateLocations it will be hit 4 - 5 time.

I have seen answers to the similar questions here (like Implement CLLocationManagerDelegate methods in Swift), but it still doesn't work for me.

What am I doing wrong?

Thanks!

Community
  • 1
  • 1
Vladimir Syeik
  • 185
  • 2
  • 7
  • So you're saying that the result is only printed once, but the breakpoint is hit multiple times? – Mike Jun 23 '14 at 15:21
  • @Mike Yes, that's correct. I've just added the following line `NSThread.sleepForTimeInterval(1.0)` to the `didUpdateLocations` handler (sleep thread for 1 sec). Now everything works fine. Definitely I'm missing something very silly :(. – Vladimir Syeik Jun 24 '14 at 14:47
  • That definitely seems funky - I wouldn't discount the possibility that this could be an Xcode 6 beta bug... – Mike Jun 24 '14 at 15:08

4 Answers4

4

Xcode 6 made lots of additions to Location Services.

1) You need to change your info.plist file to include the String "NSLocationWhenInUseUsageDescription" key. The value of this will be your applications reasoning for turning on location services: "Using location services to track your run".

2) use "[self.locationManager requestWhenInUseAuthorization];" in your code to cause the pop-up to appear with your above string.

More info is on the WWDC 2014 videos.

  • Yes, I've just versified it and in Xcode 6 Beta 6 this issue is fixed: the following workaround: `NSThread.sleepForTimeInterval(0.001)` is not required anymore. – Vladimir Syeik Aug 22 '14 at 22:01
1

This is what resolved the issue - I've added a very short sleep to the didUpdateLocations:

func locationManager(manager:CLLocationManager, didUpdateLocations locations:AnyObject[]) {
    println("locations = \(locations)")
    NSThread.sleepForTimeInterval(0.001)
}

I agree with @Mike that it looks like a very weird fix, but it is a fix. If somebody will find a better explanation/answer, please, post it.

Vladimir Syeik
  • 185
  • 2
  • 7
0

Try implementing this method to see if your location manager is being paused:

func locationManagerDidPauseLocationUpdates(manager: CLLocationManager!)

If you're getting paused, try changing the accuracy to kCLLocationAccuracyBest.

Nate Cook
  • 92,417
  • 32
  • 217
  • 178
  • Thanks, @Nate. I have not provided these pieces in the code here, but I did try `locationManagerDidPauseLocationUpdates` and `kCLLocationAccuracyBest`. Neither has solved the problem (`locationManagerDidPauseLocationUpdates` was never called). – Vladimir Syeik Jun 23 '14 at 19:09
0

In Swift 4 you can use this,

self.locationManager.requestWhenInUseAuthorization()
self.locationManager.delegate  =  self
self.locationManager.startUpdatingLocation()
smilyface
  • 5,021
  • 8
  • 41
  • 57
Angi
  • 67
  • 1
  • 4