Swift 调用位置权限的RequestWhenUseAuthorization时出错

Swift 调用位置权限的RequestWhenUseAuthorization时出错,swift,xcode,location,swift4,cllocationmanager,Swift,Xcode,Location,Swift4,Cllocationmanager,我正在尝试使用位置管理器在应用程序中检索用户的位置;正如苹果的文档中所解释的,我创建了以下方法: func startReceivingLocationChanges() { let authorizationStatus = CLLocationManager.authorizationStatus() if authorizationStatus != .authorizedWhenInUse && authorizationStatus != .author

我正在尝试使用位置管理器在应用程序中检索用户的位置;正如苹果的文档中所解释的,我创建了以下方法:

func startReceivingLocationChanges() {
    let authorizationStatus = CLLocationManager.authorizationStatus()
    if authorizationStatus != .authorizedWhenInUse && authorizationStatus != .authorizedAlways {
        locationManager.requestWhenInUseAuthorization()
        startReceivingLocationChanges()
        return
    }

    if !CLLocationManager.locationServicesEnabled() {
        displayError(withTitle: "Location Not Available", withDescription: "Enable Location Services at Settings > Privacy > Location Services", sender: self)
        return
    }

    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.distanceFilter = 100.0  // In meters.
    locationManager.pausesLocationUpdatesAutomatically = true
    locationManager.activityType = .other
    locationManager.delegate = self
    locationManager.startUpdatingLocation()
}
但是,当我启动应用程序时,此崩溃显示以下行附近的错误“Thread 1:EXC_BAD_ACCESS(code=2,address=0x16f0a7f60)”:

locationManager.requestWhenInUseAuthorization()
我指定在info.plist中添加了相对的“Privacy-Location Always and When In Using Description”和“Privacy-Location When Use Description”键


有人知道问题的原因吗?谢谢。

发现了这个问题,它与函数的递归调用有关

startReceivingLocationChanges

在函数本身内部。我解决了在ViewDidLoad方法中请求位置权限并删除递归调用的问题。

如果用户在使用时未授予权限,则代码中会出现递归等错误,请查看我的代码。假设您在info.plist中添加了“Privacy-Location Always and When Using Description”和“Privacy-Location When Use Description”键。下面的代码完美无瑕,苹果推荐

import Foundation
import CoreLocation

typealias LocateMeCallback = (_ location: CLLocation?) -> Void

class LocationTracker: NSObject {

    static let shared = LocationTracker()

    var locationManager: CLLocationManager = {
       let locationManager = CLLocationManager()
       locationManager.activityType = .automotiveNavigation
       locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
       locationManager.distanceFilter = 10

       return locationManager
    }()

    var locateMeCallback: LocateMeCallback?
    var currentLocation: CLLocation?
    var isCurrentLocationAvailable: Bool {
        return currentLocation != nil
    }

    func enableLocationServices() {
        locationManager.delegate = self
        switch CLLocationManager.authorizationStatus() {
        case .notDetermined:
            // Request when-in-use authorization initially
            locationManager.requestWhenInUseAuthorization()
        case .restricted, .denied:
            // Disable location features
            print("Fail permission to get current location of user")
        case .authorizedWhenInUse:
            // Enable basic location features
            enableMyWhenInUseFeatures()
       case .authorizedAlways:
            // Enable any of your app's location features
            enableMyAlwaysFeatures()
       }
    }

    func enableMyWhenInUseFeatures() {
       locationManager.startUpdatingLocation()
    }

    func enableMyAlwaysFeatures() {
       locationManager.allowsBackgroundLocationUpdates = true
       locationManager.pausesLocationUpdatesAutomatically = true
       locationManager.startUpdatingLocation()
    }

    func locateMe(callback: @escaping LocateMeCallback) {
        self.locateMeCallback = callback
        enableLocationServices()
    }

    private override init() {}

}


// MARK: - CLLocationManagerDelegate
extension LocationTracker: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.first else { return }
        print("locations = \(location.coordinate.latitude) \(location.coordinate.longitude)")
        locateMeCallback?(location)
    }
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print(error.localizedDescription)
    }
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        enableLocationServices()
    }
}
用法

LocationTracker.shared.locateMe {  location in
            guard let location = location else {
                print("Cann't retrieve current location of user")
                return
            }
           // do what ever you want to do with location            
        }

locationManager初始化了吗?@Andrea是的,我用“let locationManagaer=CLLocationManager()”将其初始化为类变量,您能解释一下“typealias LocateMeCallback=(\uLocation:CLLocation?->Void”行的作用吗?我知道关键字typealias用于向类型中添加另一个名称,但我不明白我们谈论的是什么类型。还有一个问题……为什么在“位置管理器”声明的花括号之后放上圆括号?@LorenzoSantini,1。typealias定义变量LocateMeCallback,使其比反复键入(uLocation:CLLocation?)->Void更具可读性。2.为什么要将圆括号放在“location manager”声明A()的卷曲括号之后:()在首次访问LocationManager时正确调用闭包,类似于延迟加载。虽然我使用的locationManager不是懒散的,但谢谢……为什么您要将NSObject子类化,而不是仅仅创建一个新类?欢迎,如果不这样做,您将遇到错误“class LocationTracker不符合NSObjectProtocol”作为CLLocationMagerDelegate的委托。来自NSObject的消息。希望能有帮助。