NSLocation doesn't wait for me to click allow

2.4k views Asked by At

When I run the code, the window pops asking for permission to use location but disappears almost immediately, not giving the user a chance to click "Allow". Is there a way to force this action before proceeding?

import UIKit
import MapKit
import CoreLocation

class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate{

var map:MKMapView?
var manager:CLLocationManager!

convenience init(frame:CGRect){
    self.init(nibName: nil, bundle: nil)
    self.view.frame = frame

    self.map = MKMapView(frame: frame)
    self.map!.delegate = self

    self.view.addSubview(self.map!)

}

override func viewDidLoad() {
    super.viewDidLoad()

    // Core Location
    manager = CLLocationManager()
    manager.delegate = self
    manager.desiredAccuracy = kCLLocationAccuracyBest

}

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

        print("The authorization status of location services is changed to: ")

        switch CLLocationManager.authorizationStatus(){
        case .Denied:
            println("Denied")
        case .NotDetermined:
            println("Not determined")
        case .Restricted:
            println("Restricted")
        default:
            println("Authorized")
        }

}

func displayAlertWithTitle(title: String, message: String){
    let controller = UIAlertController(title: title,
        message: message,
        preferredStyle: .Alert)

    controller.addAction(UIAlertAction(title: "OK",
        style: .Default,
        handler: nil))

    presentViewController(controller, animated: true, completion: nil)

}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    if CLLocationManager.locationServicesEnabled(){
        switch CLLocationManager.authorizationStatus(){
        case .Denied:
            displayAlertWithTitle("Not Determined",
                message: "Location services are not allowed for this app")
        case .NotDetermined:
                manager.requestWhenInUseAuthorization()
                manager.startUpdatingLocation()
        case .Restricted:
            displayAlertWithTitle("Restricted",
                message: "Location services are not allowed for this app")
        default:
            println("Default")
        }

    } else {
        println("Location services are not enabled")
    }

}


func locationManager(manager:CLLocationManager, didUpdateLocations locations:[AnyObject]) {

    var userLocation:CLLocation = locations[0] as! CLLocation
    var latitude:CLLocationDegrees = userLocation.coordinate.latitude
    var longitude:CLLocationDegrees = userLocation.coordinate.longitude
    var latDelta:CLLocationDegrees = 1.0
    var lonDelta:CLLocationDegrees = 1.0

    var span:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, lonDelta)
    var location:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude)
    var region:MKCoordinateRegion = MKCoordinateRegionMake(location, span)
    map!.setRegion(region, animated: true)
    manager.stopUpdatingLocation()

}
2

There are 2 answers

5
narner On BEST ANSWER

It's because you're calling manager.startUpdatingLocation() before you get the result from the manager.requestWhenInUseAuthorization(). Even though you call requestWhenInUseAuthorization, you're updating the user's location before you ever get the result of that method (I had the exact same question as you, actually!)

The answer to that question explains the solution well. Basically, you'll need to implement the locationManager:didChangeAuthorizationStatus delegate method, which is called any time the authorization status changes based on user input. If the user did authorize tracking, then you can call manager.startUpdatingLocation().

Also, for a Swift example of how to implement these methods, take look at this guide.

0
reza_khalafi On

Please try this:

import UIKit
import GoogleMaps
import CoreLocation

class StartViewController: UIViewController,CLLocationManagerDelegate,GMSMapViewDelegate {

var locationManager: CLLocationManager = CLLocationManager()

override func viewDidLoad() {
    super.viewDidLoad()

    setupLocationManager()

}

func setupLocationManager() {
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.delegate = self
    locationManager.requestWhenInUseAuthorization()
}

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    locationHandler()
}

func locationHandler() {

    if CLLocationManager.locationServicesEnabled() == true {

        if (CLLocationManager.authorizationStatus() == .denied) {
            // The user denied authorization

        } else if (CLLocationManager.authorizationStatus() == .authorizedAlways) {
            // The user accepted authorization

        } else if (CLLocationManager.authorizationStatus() == .notDetermined){
            // The user not determiend authorization

        }else if (CLLocationManager.authorizationStatus() == .authorizedWhenInUse){
            // In use

        }else{ }
    }else{
        //Access to user location permission denied!

    }


}



}//class  

Be successful.