尝试在不提示位置授权的情况下启动MapKit位置更新

时间:2015-04-01 17:04:29

标签: swift error-handling xcode6 mkmapview cllocationmanager

在我的应用程序中,我使用 MKMapKit MKUserTrackingBarButtonItem 来定位用户。当我点击此按钮时,输出控制台会返回此错误:

  

尝试在不提示位置授权的情况下启动MapKit位置更新。必须首先调用 - [CLLocationManager requestWhenInUseAuthorization]或 - [CLLocationManager requestAlwaysAuthorization]。

据我所知,导致此错误是因为尚未调用 requestWhenInUseAuthorization()。事实上, MKUserTrackingBarButtonItem 点击调用func mapViewWillStartLocatingUser ,首先预先假定 CLLocationManager requestWhenInUseAuthorization

 func mapViewWillStartLocatingUser(mapView: MKMapView!) {
    println("**** mapViewWillStartLocatingUser ****")

    // i servizi di localizzazione sono abilitati?
    if (CLLocationManager.locationServicesEnabled())
    {
        // setto il locationManager ed il delegate
        locationManager = CLLocationManager()
        locationManager.delegate = self

        // abbiamo l'autorizzazione ad accedere ai servizi di localizzazione?
        switch CLLocationManager.authorizationStatus(){
        case .Denied:
            // no
            displayAlertToEnableLocationServicesApp()
            //displayAlertWithTitle("Denied", message: "Location services are not allowed for this app")
        case .Restricted:
            // no
            displayAlertToEnableLocationServicesApp()
        case .NotDetermined:
            // bisogna chiedere all'utente
            println("Not Determined")
            if (locationManager != nil)
            {
                locationManager.requestWhenInUseAuthorization()
            }
        default:
            // si
            println("Authorized")
            if (locationManager != nil)
            {
                locationManager.desiredAccuracy = kCLLocationAccuracyBest
                locationManager.startUpdatingLocation()
            }
        }

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

        displayAlertWithTitle("Location Services are Turned Off", message: "Please open settings and turn on location services")
    }
}

// funzione della mappa
func mapView(mapView: MKMapView!, didFailToLocateUserWithError error: NSError!) {
    println("**** didFailToLocateUserWithError **** ", error)
}

// funzione della mappa
func mapView(mapView: MKMapView!, didChangeUserTrackingMode mode: MKUserTrackingMode, animated: Bool) {
    println("**** didChangeUserTrackingMode ****")
}

// funzione del CoreLocation che setta la visuale in base alla localizzaizone dell'utente
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
    println("**** didUpdateLocations ****")

    //self.mapView.showsUserLocation = true


    // aggiorno le coordinate dell'utente
    posizioneUtente = (locations[0] as CLLocation).coordinate
    //posizioneUtente = manager.location.coordinate
    println("Posizione utente aggiornata (lat: \(posizioneUtente.latitude) long: \(posizioneUtente.longitude))")

    // setto la camera sulla posizione dell'utente
    var camera = MKMapCamera(lookingAtCenterCoordinate: posizioneUtente, fromEyeCoordinate: posizioneUtente, eyeAltitude: 500)
    // utilizzo un'animazione più lenta
    UIView.animateWithDuration(1.8, animations:{
        self.mapView.camera = camera
    })

    locationManager.stopUpdatingLocation()

    // cambio l'icona del bottone della localizzazione
    //locationOutlet.setImage(UIImage(named: "LocalizzazioneEmpty"), forState: UIControlState.Normal)

}



// funzione del CoreLocation
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!)
{
    println("**** didFailWithError ****")
    println("Error: \(error.localizedDescription)")
}

// funzione del CoreLocation
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")
    }
}

我自然添加了Info.plist密钥:NSLocationWhenInUseUsageDescription。

我的问题是:如何在启动 mapViewWillStartLocatingUser 之前调用 MKUserTrackingBarButtonItem 上的 CLLocationManager requestWhenInUseAuthorization 。我希望用户在点按按钮时收到提示,而 viewDidLoad

中没有

由于 对不起我的英文

2 个答案:

答案 0 :(得分:2)

当您调用requestWhenInUseAuthorization时,系统会提示用户提供权限,此时该权限尚未获得授权。用户授予该权限后,该问题将不会再次出现。

要对用户的响应做出反应,您必须实施 来自locationManager(_:didChangeAuthorizationStatus:)协议的CLLocationManagerDelegate,如果用户授予了权限,则仅启动startUpdateLocations()

答案 1 :(得分:1)

我也在努力解决这个问题。最后,我将对locationManager的所有引用移动到一个方法,当authorizationStatus处于允许它的状态时,该方法只调用CLLocationManager中的方法:

private func enableLocationServices(enabled: Bool) {
    switch CLLocationManager.authorizationStatus() {
    case .AuthorizedAlways: fallthrough
    case .AuthorizedWhenInUse:
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        if enabled {
            locationManager.startUpdatingLocation()
        }
        else {
            locationManager.stopUpdatingLocation()
        }
    case  .NotDetermined: break
    case .Denied: break
    case .Restricted: break
    }
}

执行此操作后,我仍然收到“尝试启动MapKit位置更新而不提示位置授权”警告。事实证明仍然让我感到头疼的是:

        mapView.showsUserLocation = true

直到我将此行从我的viewDidLoad移到switch语句启动位置服务,警告就消失了。我不明白这条线会导致问题,因为它不是CLLocationManager类的一部分;但在考虑之后它确实有意义。地图视图使用位置服务将闪烁的蓝点放在屏幕上。最终的工作解决方案(对我而言)看起来像:

let locationManager = CLLocationManager()

// MARK: Viewcontroller lifecyle

override func viewDidLoad() {
    super.viewDidLoad()

    locationManager.requestWhenInUseAuthorization()
    locationManager.delegate = self
    enableLocationServices(true)
.
.
}

.
.
// MARK: CLLocationManager Delegate Methods

func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
    switch status {
    case .AuthorizedAlways: fallthrough
    case .AuthorizedWhenInUse:
        enableLocationServices(true)
    default:
        break
    }
}

private func enableLocationServices(enabled: Bool) {
    switch CLLocationManager.authorizationStatus() {
    case .AuthorizedAlways: fallthrough
    case .AuthorizedWhenInUse:
        mapView.showsUserLocation = true
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        if enabled {
            locationManager.startUpdatingLocation()
        }
        else {
            locationManager.stopUpdatingLocation()
        }
    case  .NotDetermined: break
    case .Denied: break
    case .Restricted: break
    }
}