当前位置权限对话框消失得太快

我的应用程序获取用户的位置,获取坐标,并提供与他们的目的地或原点的距离。所有这些可能的目的地都显示在表视图中,因此我在填充表的同时获取用户的坐标。唯一的问题是,询问用户位置的警报视图出现后很快就消失了,以至于无法点击它!

有没有办法在应用程序首次加载时手动显示这个警报?我尝试在应用程序加载时获取用户的位置,试图强制显示警报,但没有工作。

36777 次浏览

我陷入了同样的问题(至少是症状)。 在我的例子中,问题出现在 - (void)applicationWillResignActive:(UIApplication *)application;方法中,我释放 CLLocationManager实例是为后台转换做准备的一部分。当我删除它,并离开它只在 - (void)applicationDidEnterBackground:(UIApplication *)application;的问题是消失了。棘手的部分是,核心位置警报 DO 在应用程序仍处于前台时挂起它。希望能对你有所帮助,花了我很多时间才找到那个混蛋:)

虽然很难追踪,但是解决方案很简单。

经过反复试验,我发现当你第一次尝试访问应用程序中的任何位置服务时,位置访问对话框会弹出来,如果在用户响应对话框之前释放 CLLocationManager对象,对话框会自动消失(没有任何用户交互)。

我在我的 viewDidLoad方法中创建了一个 CLLocationManager实例。因为这是方法的本地实例,所以该实例在方法完成执行后由 ARC 释放。一旦实例被释放,对话框就消失了。解决办法很简单。将 CLLocationManager实例从方法级变量更改为类级实例变量。现在,只有在卸载类之后才释放 CLLocationManager实例。

我知道这是一个非常晚的答复。但它可能有助于某人。 我也面临着同样的问题,花了一个小时来确定这个问题。 一开始我的代码是这样的。

CLLocationManager *locationManager = [[CLLocationManager alloc] init];
[locationManager startUpdatingLocation];


CLLocation *location = locationManager.location;
//my stuff with the location


[locationManager release];

现在位置警报很快就消失了。 当我取消注释最后一行时,它正常工作。

   // [locationManager release];

我也遇到了这个问题,但是在我的情况下,解决方案被证明是完全不同于接受的答案。

在我的应用程序中,我从 applicationWillResignActive呼叫 stopUpdatingLocation。这是一个问题,因为当权限对话框出现时会调用 applicationWillResignActive。这导致 startUpdatingLocation之后立即出现 stopUpdatingLocation,这就是为什么对话框会立即消失的原因。

解决方案只是从 applicationDidEnterBackground调用 stopUpdatingLocation

同样的症状,不同的原因: 不要连续调用 startUpdatingLocation多次

我不小心构造了一些东西,以至于代码无意中连续两次调用 startUpdatingLocation,这显然很糟糕。它也可能与队列的选择有关,因为我正在等待开始更新等待网络请求的结果,但我不需要做任何 GCD 魔术来修复它... 只需要确保我没有重复开始。

希望有人能从我的痛苦中受益。 :)

您最常将 locationManager 变量定义为全局对象。

@interface ViewController : UIViewController
{
CLLocationManager *locationManager;
}
@end


@implementation ViewController


- (void)viewDidLoad
{
[super viewDidLoad];


CLLocationManager *locationManager = [[CLLocationManager alloc] init];
[locationManager startUpdatingLocation];
}

这是在我使用 iOS 模拟器时发生的。我确定它的发生是因为我的 Run Scheme 正在模拟一个位置。我认为这与在启动时调用 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
}
}

Swift 4和 iOS 11 :

确保在 .plist文件中添加了隐私行(包括 一直都是何时使用) ,并将 CoreLocation框架添加到项目中

更改后,位置权限对话框将正确显示:

locationManager.requestAlwaysAuthorization()

与:

locationManager.requestWhenInUseAuthorization()

P.S .: 我已经尝试了 全部建议,但都失败了(请求对 locationManager 授权到 viewDidLoadvar而不是 let,请求后不要启动 startUpdatingLocation()。.我认为这是一个错误,我希望他们能尽快解决这个问题。.

我也遇到过和你一样的情况。

  • 我的解决方案从局部变量更改为成员实例。
  • 原因是在方法完成后,本地实例无效,这个方法包含了本地变量(扩展我的 locationManager)
  • 我的 Env: Xcode9.3.1


#import
@interface ViewController ()


@end


@implementation ViewController
@synthesize locManager; // after
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.


//MyLocationService *locManager = [[BSNLocationService alloc]init:nil]; // before. the loc. delegate did not work because the instance became invalid after this method.
self->locManager= [[MyLocationService alloc]init:nil]; // after
locManager.startService;
}


我也遇到过类似的情况。经过调试我发现

let locationManager = CLLocationManager()

是在方法范围中调用的,但应该是全局调用的。

为什么?

简而言之,locationManager 是在方法返回之后发布的。但是,在用户给予或拒绝许可之前,不应该发布它

我使用 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变量变懒解决了这个问题:

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()
}
}