Location Services not detected at First launch

Discussion in 'iOS Programming' started by xArtx, Mar 6, 2013.

  1. xArtx macrumors 6502a

    Joined:
    Mar 30, 2012
    #1
    Hi Guys,
    Small problem.. I'm checking for both conditions,
    Location Services are globally disabled,
    or Location Services were not authorised for the App.

    I use this code straight after enabling Location Services in the App.

    Code:
        if (![CLLocationManager locationServicesEnabled]) {errorcode = 1;}
        if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {errorcode = 1;}
            
        if (errorcode == 1) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Location Services"
                                                  message:@"Functionality of this program is limited to Map Browse Mode without Location Services enabled."
                                                  delegate:nil
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil];
        [alert show];     
        }
    
    So if "errorcode" is set to 1 I can go about handling the absence of core location.
    Problem is, every time I delete the App from a device, and run it for the first time,
    I can deny the App's permission to use Location Services, and errorcode
    is not set to 1, and the alert doesn't show, and Location Services are not working.
    The second time I run the App, all is well. The alert does show,
    and error code is set to 1.

    Any ideas what I'm doing wrong?
    Surely if this was an Apple bug it would have been sorted by now.
    Cheers, Art.
     
  2. ArtOfWarfare macrumors G3

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #2
    Use the debugger. Is any of this code being executed on the first launch at all? If not, why not? From where is the method you shared with us being called?
     
  3. xArtx thread starter macrumors 6502a

    Joined:
    Mar 30, 2012
    #3
    Yes, because the error handling is straight after starting corelocation:
    Code:
      self.locationManager = [[CLLocationManager alloc] init];
        locationManager.desiredAccuracy = kCLLocationAccuracyBest;
        locationManager.delegate = self;
        [locationManager startUpdatingHeading];    
        [locationManager startUpdatingLocation]; 
    
    and that always works if I allow it.

    I was looking at the docs, and found that kCLAuthorizationStatusDenied
    or granted are not the only results.
    There is a result that means "not known yet".
    It might do to sit in a while loop until it gives a straight answer.

    I have found through testing, that the old fashioned way (pre 4.xx) :
    Code:
    -(void)locationManager:(CLLocationManager *)manager 
          didFailWithError:(NSError *)error
    {
    errorcode = 1;
    }
    
    can report an error for reasons other than core location wasn't granted.
    It failed on me once when I resumed the App, where location services were never denied either globally, or for the App.
     
  4. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #4
    Careful, you might end up blocking the main run loop, which might prevent the user from being able to respond to the prompt to grant or deny access.
     
  5. xArtx thread starter macrumors 6502a

    Joined:
    Mar 30, 2012
    #5
    Yep, that happened. It never leaves the boot screen, and the prompt never arrives.
    I'll have to allow it to pass, and just keep checking until I see a result I want.

    So basically, never do this:
    Code:
        while ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
        int cccvvv = 0; // waste a bit of time
        cccvvv++;
        if (cccvvv > 100) {cccvvv = 0;}
        } // not yet determined
    

    But that makes me pretty sure the value is kCLAuthorizationStatusNotDetermined.

    ----------

    And interestingly, this is called after you select OK or Do Not Allow.
    Only for the first launch.
    But the App is working and refreshing frames while the prompt is up.

    Code:
    - (void)applicationDidBecomeActive:(UIApplication *)application
    {
        resumed = 1;
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }
    
     
  6. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #6
    As stated in the CLLocationManager Class Reference, you should be checking if the desired services are available before you instantiate your CLLocationManager.

    And have you looked into CLLocationManagerDelegate's locationManager:didChangeAuthorizationStatus: method yet?

    Also, by the way, you still haven't told us where (i.e. in which method/class) you are running any of the provided code.
     
  7. xArtx thread starter macrumors 6502a

    Joined:
    Mar 30, 2012
    #7
    It does seem to be working as expected now :)

    I was initially starting it in viewdidload, but moved it to my main loop when
    I decided to distribute it.. so I can try to restart it.

    I know when the program is resumed,
    so I suppose I can check for authorisation change there.
    If the App is resumed, I pause track logging to give the device a chance to
    get a good quality position before the log is ruined with poor locations.

    I suppose I should check location services are available for the device,
    even though I plan to require GPS in plist settings. Then it's there if I change
    my mind about that for an update.
     

Share This Page