John
John

Reputation: 3

Updating Current Location

let locationManager = CLLocationManager()

@IBOutlet var map: MKMapView!

func getLocation ()-> CLLocation! {
    self.locationManager.startUpdatingLocation()
    sleep(1)
    self.locationManager.stopUpdatingLocation()
    var x = locationManager.location
    return x
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
    self.locationManager.requestWhenInUseAuthorization()

    var mapCoord:CLLocation! = getLocation()
    var mapLat:Double! = mapCoord.coordinate.latitude //Where the thread error is
    var mapLong:Double! = mapCoord.coordinate.longitude
//Setup of the rest of the map is completed

My code is as above, in Swift. I am receiving an error:

thread error of an unexpected nil value

while calling for coordinates from the getLocation() function. I changed both mapLat and mapLong to test what is causing the nil. My app will load but I receive a message in the output saying my current location cannot be updated as I have no asked for permission; however, I do have the function to request for permission in the beginning of my viewDiDLoad(). I have used this format before on a different project and it has worked, so I know I must be missing something obvious, etc. Thank you for any help.

Upvotes: 0

Views: 93

Answers (2)

aahrens
aahrens

Reputation: 5590

Try this. You'll need to request permission and only when you have a valid permissions can you start updating.

typealias Location = CLLocation

//MARK: Private Variables
private let locationManager = CLLocationManager()
private var currentLocation: Location? {
    didSet {
        // You have a new location. Use it somehow
    }
}

//MARK: View Lifecycle
override func viewDidLoad() {
    super.viewDidLoad()

    locationManager.delegate = self
}

override func viewWillAppear(animated: Bool) {
    // Ask for permission if necessary
    let currentStatus = CLLocationManager.authorizationStatus()
    if currentStatus == .Restricted || currentStatus == .Denied || currentStatus == .NotDetermined {
        locationManager.requestWhenInUseAuthorization()
    } else {
        locationManager.startUpdatingLocation()
    }
}

//MARK: CLLocationManagerDelegate
func locationManager(manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
    if status == .AuthorizedWhenInUse {
        locationManager.startUpdatingLocation()
    }
}

func locationManager(manager: CLLocationManager!, didUpdateToLocation newLocation: CLLocation!, fromLocation oldLocation: CLLocation!) {
    newLocation
    currentLocation = newLocation
    locationManager.stopUpdatingLocation()
}

Upvotes: 0

Duncan C
Duncan C

Reputation: 131471

Your code is very wrong, and won't work.

You can't write procedural code that starts location updates, pauses, stops location updates, and then gets a location.

You have to set yourself up as the location manager's delegate, start location updates, and return.

At some point after that, the system will call your locationManager:didUpdateLocations method.

Then you need to check the accuracy of the location that you get and make sure it's accurate enough. (Frequently the first several location readings you get when the GPS is first powered up are quite bad, and don't meet your desired accuracy. I suggest a horizontal accuracy of 200 M or so, depending on your app's requirements.

If you get a reading that is accurate enough you can turn off updates and use that location for your needs.

P.S. Never, ever, EVER use the sleep() function on the main thread. In fact, as a novice iOS Mac OS developer, you should pretend that the sleep function doesn't exist.

Upvotes: 1

Related Questions