虽然很难追踪,但这个问题的解决方案非常简单。
在进行任何位置服务的访问时,如果应用程序尝试首次访问,则会弹出位置访问对话框。经过多次尝试和错误,我发现,如果用户在响应对话框之前释放了 CLLocationManager
对象,则该对话框会自动消失(无需任何用户交互)。
在我的 viewDidLoad
方法中创建了一个 CLLocationManager
实例。由于这是方法级别的局部变量,所以实例在方法执行完成后,由 ARC 释放了。一旦实例被释放,对话框就会消失。解决方案很简单。将 CLLocationManager
实例从方法级变量更改为类级实例变量。现在,只有在卸载类时才会释放 CLLocationManager
实例。
let locationManager = CLLocationManager()
该方法作用域内调用了locationManager,但应该在全局范围内调用。
为什么呢?
简单来说,locationManager在方法返回后被释放了。但它直到用户授权或拒绝之前都不应该被释放。
startUpdatingLocation
。
由于我错误地构建了代码,导致无意中连续两次调用 startUpdatingLocation
,这显然是不好的。这也可能与队列的选择有关,因为我正在等待网络请求的结果来开始更新,但我不需要进行任何GCD操作来修复它……只需要确保不重复启动即可。CLLocationManager *locationManager = [[CLLocationManager alloc] init];
[locationManager startUpdatingLocation];
CLLocation *location = locationManager.location;
//my stuff with the location
[locationManager release];
// [locationManager release];
我也遇到了同样的问题(至少症状相似)。
在我的情况下,问题出现在- (void)applicationWillResignActive:(UIApplication *)application;
方法中,因为我正在准备进入后台转换而释放我的CLLocationManager
实例。当我将其从该方法中移除并仅留在- (void)applicationDidEnterBackground:(UIApplication *)application;
中时,问题就解决了。
棘手之处在于,Core Location警报在应用程序仍在前台运行时会挂起你的应用程序。
希望这对你有所帮助,对我来说,寻找这个混蛋花费了很多时间 :)
applicationWillResignActive
调用stopUpdatingLocation
。 这是一个问题,因为当权限对话框出现时会调用applicationWillResignActive
。这导致stopUpdatingLocation
在startUpdatingLocation
之后立即停止工作,这就是为什么对话框会立即消失的原因。applicationDidEnterBackground
中调用stopUpdatingLocation
即可。请确保在你的.plist
文件中已添加隐私权限行(总是和使用时),并向你的项目添加CoreLocation
框架。
当我更改了以下内容后,位置权限对话框正确显示:
locationManager.requestAlwaysAuthorization()
使用:
locationManager.requestWhenInUseAuthorization()
P.S.: 我已经尝试了所有建议,但都失败了(请求授权到viewDidLoad
,使用var
代替let
来处理locationManager,不要在请求后启动startUpdatingLocation()
..我认为这是一个错误,希望他们能尽快解决它..
我在使用iOS模拟器时遇到了这个问题。后来我发现是因为我的运行方案正在模拟位置,导致了这个弹窗被关闭。我认为这与在启动时调用 locationManager.startUpdatingLocation()
的效果相同。
在编辑方案对话框中取消勾选“允许位置模拟”复选框可以解决此问题。一旦设置好权限并正常工作,您可以重新启用位置模拟,随后模拟器将正常工作。
我将locationManager
作为实例变量,但在Swift 5、Xcode 11中仍然没有帮助(请参见下文):
class MapViewController: UIViewController {
var locationManager: CLLocationManager {
let locationManager = CLLocationManager()
locationManager.desiredAccuracy = .greatestFiniteMagnitude
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
return locationManager
}
override func viewDidLoad() {
super.viewDidLoad()
locationManager.startUpdatingLocation()
}
}
然而,将locationManager
变量设置为lazy可以解决该问题:
class MapViewController: UIViewController {
lazy var locationManager: CLLocationManager = {
let locationManager = CLLocationManager()
locationManager.desiredAccuracy = .greatestFiniteMagnitude
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
return locationManager
}()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.startUpdatingLocation()
}
}
SWIFT 4 @Zoli 的解决方案将如下所示:
class WhateverViewController: UIViewController {
let locationManager = CLLocationManager() // here is the point of the @Zoli answer
// some code
override func viewDidLoad() {
super.viewDidLoad()
// some other code
locationManager.requestWhenInUseAuthorization()
// some other code
}
}