现在应用中经常用到定位,定位代码比较简单。调试的过程中发现在弹窗权限弹窗的时候就会触发didFailWithError,当用户拒绝定位就会触发第二次回调。
第一次的error:code == CLError.denied.rawValue && domain = kCLErrorDomain
class TZLocationManager: NSObject {
typealias SuccessBlock = ([CLLocation]) -> Void
typealias FailureBlock = (Error) -> Void
private let locationManager = CLLocationManager()
/// 定位成功的回调block
private var successBlock: SuccessBlock?
/// 定位失败的回调block
private var failureBlock: FailureBlock?
/// 一次性定位
public func startLocation(successBlock: SuccessBlock?, failureBlock: FailureBlock?) { self.successBlock = successBlock
self.failureBlock = failureBlock
locationManager.delegate = self
locationManager.startUpdatingLocation()
locationManager.requestWhenInUseAuthorization()
}
public func stopUpdatingLocation() {
locationManager.stopUpdatingLocation()
}
}
extension TZLocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
successBlock?(locations)
locationManager.delegate = nil
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
// 定位权限弹窗的时候, 可能失败回调了
let err = error as NSError
if err.code == CLError.denied.rawValue && err.domain = kCLErrorDomain {
print("定位失败:没有定位权限?")
}
failureBlock?(error)
locationManager.delegate = nil
}
}
经过一番排查才发现定位的用法一直是错的。我们需要先判断是否有定位权限,没有就去请求权限,等有权限了再去请求定位。
if status == .authorizedWhenInUse || status == .authorizedAlways {
locationManager.startUpdatingLocation()
} else {
locationManager.requestWhenInUseAuthorization()
}
下边是正确用法。
class TZLocationManager: NSObject {
typealias SuccessBlock = ([CLLocation]) -> Void
typealias FailureBlock = (Error) -> Void
private let locationManager = CLLocationManager()
/// 定位成功的回调block
private var successBlock: SuccessBlock?
/// 定位失败的回调block
private var failureBlock: FailureBlock?
/// 一次性定位
public func startLocation(successBlock: SuccessBlock?, failureBlock: FailureBlock?) { self.successBlock = successBlock
self.failureBlock = failureBlock
locationManager.delegate = self
let status = CLLocationManager.authorizationStatus()
if status == .authorizedWhenInUse || status == .authorizedAlways {
locationManager.startUpdatingLocation()
} else {
locationManager.requestWhenInUseAuthorization()
}
}
public func stopUpdatingLocation() {
locationManager.stopUpdatingLocation()
}
}
extension TZLocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { successBlock?(locations)
locationManager.delegate = nil
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
// 定位权限弹窗的时候, 可能失败回调了
failureBlock?(error)
locationManager.delegate = nil
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedAlways, .authorizedWhenInUse:
locationManager.startUpdatingLocation()
case .denied, .restricted:
let error = NSError(domain: kCLErrorDomain, code: CLError.denied.rawValue)
failureBlock?(error)
locationManager.delegate = nil
default:
break
}
}
}