Current location permission dialog disappears too quickly
Asked Answered
K

12

184

My app takes the users location, gets the co-ordinates , and provides a distance to or from their destination or origin. All these possible destinations are shown in a table view, so I'm getting the users co-ordinates at the same time as populating the table. The only thing is, the alert view that asks for the users location appears then disappears so quickly it's impossible to click it!

Is there any way to manually present this alert when the app first loads? I tried getting the users location when the app loads up to try and force the alert to show, but that didn't work.

Koffler answered 25/10, 2011 at 11:56 Comment(0)
S
744

While difficult to track down, the solution for this is quite simple.

Through much trial and error I found out that while the location access dialog pops up when you try to access any location services in the app for the first time, the dialog disappears on its own (without any user interaction) if the CLLocationManager object is released before the user responds to the dialog.

I was creating a CLLocationManager instance in my viewDidLoad method. Since this was a local instance to the method, the instance was released by ARC after the method completed executing. As soon as the instance was released, the dialog disappeared. The solution was rather simple. Change the CLLocationManager instance from being a method-level variable to be a class-level instance variable. Now the CLLocationManager instance is only released once the class is unloaded.

Selachian answered 27/2, 2012 at 23:34 Comment(11)
Just hit the same problem with Xamarin.iOS. Make CLLocationManager class scope and the dialog remains visible.Eiger
Yaaaaa.... if you could go ahead and give yourself a raise, that'd be greeeeeaaaat. (Seriously, this is a big save for me too)Keven
This saved me. Apparently locationManager:didChangeAuthorizationStatus: was being called even though it had not changed from kCLAuthorizationStatusNotDetermined and I was tearing it down.... yanking the rug out from under my own feet.Prevenient
I have to join this party too. Here, get an Internet High Five from me !Ribera
@Selachian same problem with "Calendar App" please check #30975264 How can we handle this.. As i am not using location service in my app.English
I experience this issue with a Cordova geolocation plugin (in the file github.com/apache/cordova-plugin-geolocation/blob/master/src/… ) but am not familiar enough with Objective-C to correct it myself based on your short indications. Could you or someone elaborate a bit more about the code of your solution? Thank you so much.Beneficent
Anyone having this issue in Swift make sure you move the declaration of LocationManager outside viewDidLoad. Cheers!Mcgray
Hey , I am actually calling a method present in another class from the app delegate using a reference to that class . But by the time the I can give "allow" , The dialog box disappers. I am sure that ARC frees the object . and So , how to overcome that , The CLLocationManager() variable is a class variable declared at the top of the class . But still , this doesn't work . Can Anyone helpCornelison
Still valid with Swift 4 and iOS 11.2! greatArtel
ah.. simple fix. but great. (worked with swift 4, xcode 9.2)Mori
Perfect answer, this really helped me alot after 30 minutes of try. Now i have just created and initialized the CLLocationManager variable on the class level instead of function level like this: let locationManager = CLLocationManager() and used this variable in the class.Sukiyaki
P
7

Same symptom, different cause: do not to call startUpdatingLocation more than once in a row.

I had accidentally structured things such that the code was unintentionally calling startUpdatingLocation twice in a row, which is apparently bad. It might also have had something to do with choice of queue since I was waiting to start updating pending the result of a network request, but I didn't need to do any GCD magic to fix it...just needed to make sure I didn't repeat the start.

Hope someone's able to benefit from my pain. :)

Preoccupancy answered 19/3, 2015 at 20:2 Comment(0)
B
7

I have faced the similar situation. After debugging I found

let locationManager = CLLocationManager()

is called in a method scope, but it should be called globally.

Why?

In a nutshell, locationManager has been released after the method had returned. But it shouldn't be released until user give or deny permission

Bain answered 23/6, 2019 at 12:8 Comment(0)
P
4

I fall into the same issue (at least by symptoms). In my case the problem was in the - (void)applicationWillResignActive:(UIApplication *)application; method, where I was releasing my CLLocationManager instance as part of preparing for background transition. When I removed it and left it only in - (void)applicationDidEnterBackground:(UIApplication *)application; the problem is gone.
The tricky part is that Core Location alert DO suspend your application while it still in foreground.
Hope that it will help you, took me a lot of time to found that bastard :)

Pulverize answered 17/11, 2011 at 16:8 Comment(0)
K
4

I know this is a very late reply. But it may help someone. I also faced the same problem and spent an hour to identify the issue. At first my code was like this.

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

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

    [locationManager release];

Now the location alert disppeared quickly. When I uncomment the last line it is working correctly.

   // [locationManager release];
Karlykarlyn answered 17/7, 2012 at 11:36 Comment(1)
This is true. The only caveat I would add to this answer is that when your project has ARC enabled, you don't need to include the release statement in your code and you will still run into this problem. The only way to resolve the issue in that scenario is the make the variable class-level instead of method-level.Selachian
C
3

I ran into this problem, also, but the solution in my case turned out to be completely different than the accepted answer.

In my app, I was calling stopUpdatingLocation from applicationWillResignActive. This was a problem because applicationWillResignActive is called when the permission dialog appears. This was causing stopUpdatingLocation immediately after startUpdatingLocation, which is why the dialog would immediately disappear.

The solution was simply to call stopUpdatingLocation from applicationDidEnterBackground instead.

Cupreous answered 12/9, 2013 at 6:36 Comment(0)
M
2

This was happening to me while using the iOS Simulator. I determined that it was occurring because my Run Scheme was simulating a location. I think this has the same effect as calling locationManager.startUpdatingLocation() at launch and so it was closing the dialog.

Un-checking the "Allow Location Simulation" checkbox in the Edit Schemes dialog fixed the issue. Once it works as you want it to and the permission is set, you can re-enable the location simulation and the simulator will work fine from then on.

Mark answered 22/1, 2017 at 3:58 Comment(1)
This worked to some extend for me. Atleast I got to see the dialogOutofdoor
B
2

Swift 4 and iOS 11:

Be sure to have added privacy lines (both always and whenInUse) to your .plist file and add CoreLocation Framework to your project

The location permission dialog appears correctly when I've changed :

locationManager.requestAlwaysAuthorization()

with:

locationManager.requestWhenInUseAuthorization()

P.S.: I've tried ALL advices and all fails (request authorization to viewDidLoad, var instead of let for locationManager, don't start startUpdatingLocation() after request..I think it's a bug and I hope they will resolve it as soon as possible..

Brushwork answered 9/10, 2017 at 8:14 Comment(2)
I have followed all the advices too, but I always have the same issue. The location permission dialog appears briefly, then disappear immediately. Then my notification dialog permission appears (this one is normal), when I press accept or decline, an other location permission appears (this time it stays and let me accept or decline).Marshamarshal
@BitoQ Yes, for me too. Same situation but at least we can see this dialog, I hope with the next iOS 11.1 they'll correct this bug..Brushwork
T
2

I had the locationManager as instance var but still that did not help in Swift 5, Xcode 11 (see below):

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

However, making locationManager var lazy fixed the issue:

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()
    }
}
Tatyanatau answered 19/9, 2020 at 17:18 Comment(0)
Z
1

SWIFT 4 @Zoli solution will look like:

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
    }
}
Zedekiah answered 9/8, 2017 at 12:33 Comment(0)
H
0

you most define locationManager variable as global object.

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

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    CLLocationManager *locationManager = [[CLLocationManager alloc] init];
    [locationManager startUpdatingLocation];
}
Hiatt answered 31/8, 2016 at 11:4 Comment(0)
H
0

I met same situation of yours.

  • My solution was changed from local variable to member instance.
  • The cause was that the local?instance was invalid after the method was finished which includes the local the variable(of extend my locationManager)
  • My 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;
}

Heeler answered 25/5, 2018 at 7:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.