DrWhat
DrWhat

Reputation: 2490

Why isn't locationManager didUpdateLocation working?

With CoreLocation.Foundation added to the BuildPhase and imported at the top of the file, I can get location information if I put the following into a view controller with a button:

@IBAction func locationButton(sender: AnyObject) {
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestWhenInUseAuthorization()
    locationManager.startUpdatingLocation()
}

It goes on to locationManager didUpdateLocations with a CLGeocoder().reverseGeocodeLocation completionHandler that displays the location info in another function - this works.

BUT, it doesn't work when I try to transfer this same code in my data model. I set up the model with the following:

import CoreLocation

class Record: NSObject, CLLocationManagerDelegate
{
    let locationManager = CLLocationManager()

Because there's no button, I've put the locationManager code into:

        override init()
{
    iD = NSUUID().UUIDString

    super.init()

    if (CLLocationManager.locationServicesEnabled())
    {
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.requestWhenInUseAuthorization()

        switch CLLocationManager.authorizationStatus() {
        case .AuthorizedWhenInUse, .AuthorizedAlways:
            locationManager.startUpdatingLocation()
        case .NotDetermined:
            locationManager.requestWhenInUseAuthorization() // or request always if you need it
        case .Restricted, .Denied:
            print("tell users that they need to enable access in settings")
        default:
            break
        }
        print("Location services available")
        if CLLocationManager.authorizationStatus() == .NotDetermined
        {
            print("Still Not Determined")
        }
    } else { print("Location services not available") }

}

I get 'Location services available'. But the following code never prints anything to console, nor does it call the function toSetLocationStamped.

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!)
{
    print("started location man")
    CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler:        //pass the location co-ordinates
        {
            (placemarks, error) -> Void in

            if (error != nil)
            {
                println("Reverse geocoder failed with error" + error.localizedDescription)
                return
            }

            if placemarks.count > 0         //process the location array (placemarks)
            {
                let pm = placemarks[0] as! CLPlacemark
                self.toSetLocationStamped(pm)
                print("got here")
            } else
            {
                println("Problem receiving data from geocoder")
            }
    })
}

If I put a deinit the class Record, with a simple print log, there is no output.

deinit
{
    print("deinit")
}

I'm initializing a dummyRecord: Record from a required init in MasterViewController class:

class MasterViewController: UITableViewController
{
var records = [Record]()
var subjectDescription: String?

// weak var delegate: MonsterSelectionDelegate?        // property for object conforming to MSDelegate

required init(coder aDecoder: NSCoder)      //      // coder because class is loaded from Storyboard
{
    super.init(coder: aDecoder)

    var dummyRecord1 = Record()
    dummyRecord1.details = "All was very good and strong with a little bit of lemon on the side of the hill."
    dummyRecord1.dateTimeEntered = NSDate(dateString: "2015-07-22")
    dummyRecord1.subject = "Clouds"
    dummyRecord1.locationEntered = "Drittelsgasse 1, 69493 Großsachsen, Germany."
    dummyRecord1.photos.append(UIImage(named: "zombies.jpg")!)

    records.append(dummyRecord1)
}

Upvotes: 1

Views: 987

Answers (1)

Andriy Gordiychuk
Andriy Gordiychuk

Reputation: 6282

After you call

self.locationManager.requestWhenInUseAuthorization()

you cannot immediately start updating location. That call is asynchronous.

Here is how you should properly do it:

1) Check the authorisation status:

switch CLLocationManager.authorizationStatus() {
    case .AuthorizedWhenInUse, .AuthorisedAlways:
        locationManager.startUpdatingLocation()
    case .NotDetermined:
        locationManager.requestWhenInUseAuthorization() // or request always if you need it
    case .Restricted, .Denied:
        // tell users that they need to enable access in settings
    default:
        break
}

2) If you have previously authorised your app this should update location. However, if you didn't a popup will appear. In order to respond to the change in the authorisation status you need to add another function:

func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
    if (status == .AuthorizedAlways) || (status == .AuthorizedWhenInUse) {
        locationManager.startUpdatingLocation()
    }
}

Upvotes: 2

Related Questions