a432511
a432511

Reputation: 1905

ABAddressBookGetAuthorizationStatus Denied After Authorized In Settings

I am attempting to more gracefully handle denied contact book permissions, but I have found a scenario that doesn't work properly. I am running Xcode 7 and Swift 2.0.

First I explain why the permission is relevant to the app experience and then when they decide it should be allowed they can tap a button with calls:

ABAddressBookRequestAccessWithCompletion(nil) {
    (granted:Bool, err:CFError!) in
    if(granted){
        // Get contacts
    }
}

Should they decline the iOS permission dialog, I prompt them later using the following code after checking ABAddressBookGetAuthorizationStatus():

func evaluateContactAccess(requestCompleted: (granted: Bool) -> ()) {
    let status = ABAddressBookGetAuthorizationStatus();
    switch status {
    case .Authorized:
        requestCompleted(granted: true);
    case .NotDetermined:
        ABAddressBookRequestAccessWithCompletion(nil) {
            (granted:Bool, err:CFError!) in
                requestCompleted(granted: granted);
        };
    case .Restricted, .Denied:
        let alertController = UIAlertController(
            title: "Contact Access Disabled",
            message: "Message about access here...",
            preferredStyle: .Alert)

        let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
        alertController.addAction(cancelAction)

        let openAction = UIAlertAction(title: "Open Settings", style: .Default) { (action) in

            if let url = NSURL(string:UIApplicationOpenSettingsURLString) {

                UIApplication.sharedApplication().openURL(url)
            }
        }
        alertController.addAction(openAction)

        self.presentViewController(alertController, animated: true, completion: nil);

        NSNotificationCenter.defaultCenter().addObserver(self, selector: "checkAndProceed", name: UIApplicationWillEnterForegroundNotification, object: nil)
    }
}

func checkAndProceed() {
    let status = ABAddressBookGetAuthorizationStatus()
    switch status {
    case .Authorized:
        // get contacts
    case .NotDetermined, .Restricted, .Denied:
        // debugger says status = .Denied at this point every time
    }
}

Now the app's iOS settings page opens accordingly and the user is given the opportunity to grant contact access. Let's say they grant access to the contact book and switch back to the app - no matter how many times I call ABAddressBookGetAuthorizationStatus() after the app resumes it always returns ABAuthorizationStatus.Denied as if it didn't detect the user changing the permission to Authorized in the app's iOS settings page.

I filed a bug with Apple just in case, but I was wondering if anyone else had a trick to get this working.

Thanks!

Upvotes: 2

Views: 1130

Answers (1)

matt
matt

Reputation: 535119

You have not given sufficient information about what your code is and how you are testing, despite my repeated requests, so at this point I can only guess. And my guess is that your testing procedure is flawed. You cannot test this feature while running in the Xcode debugger. If you untether your device and test purely on the device, you will find that when you return to your app from Settings, if your app then checks again for the authorization status, it gets the authorization status right.

Upvotes: 0

Related Questions