0

I have a view controller where I am trying to access the user's address book on viewDidLoad. When the user lands on the view controller, I want to have an alert window popup asking them if the app can access the contacts in their address book, and then they can select "Ok" or "Don't Allow."

What's weird is I was under the impression that my code was setup correctly to do this. However, whenever I run the app on my iPhone and visit this view controller it doesn't even ask me for permission and just automatically accesses my contacts. I have even tried deleting the app and all of it's data from my iPhone, and then re-running in xcode and on my iPhone.

I'm not sure if it's a glitch because I'm the developer, or if there's something wrong with my code.

Here is the code I use to access the address book in viewDidLoad:

- (void)viewDidLoad {

[super viewDidLoad];

// Do any additional setup after loading the view.

//Asks for access to Address Book.

ABAddressBookRef m_addressbook =  ABAddressBookCreateWithOptions(NULL, NULL);


ABAddressBookCopyArrayOfAllPeople(m_addressbook);


__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        @autoreleasepool {

            // Write your code here...
            // Fetch data from SQLite DB
        }
    });

    ABAddressBookRequestAccessWithCompletion(m_addressbook, ^(bool granted, CFErrorRef error)

    {
        accessGranted = granted;

        NSLog(@"Has access been granted?: %hhd", accessGranted);
        NSLog(@"Has there been an error? %@", error);


        dispatch_semaphore_signal(sema);
    });
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
else { // we're on iOS 5 or older
    accessGranted = YES;

    NSLog(@"Address book access has been granted.");
}

if (accessGranted) {


    NSArray *allContacts = (__bridge_transfer NSArray
                            *)ABAddressBookCopyArrayOfAllPeople(m_addressbook);

And then basically if access is granted I start loading all of the names and phone numbers into the view controller's UITableView.

I really need to figure out why this is behaving this way and would also like to add an alert view that asks the user if they would like to allow access to the address book contacts.

Is it not actually asking for access because my code is wrong? Because it knows I'm the developer? Like I said I am running this after deleting the app and all of it's data from my iPhone.

UPDATE: I am using iOS 7.0.4 if that makes a difference.

user3344977
  • 3,584
  • 4
  • 32
  • 88

3 Answers3

2

One mistake I see in your code is that you have this:

if (ABAddressBookRequestAccessWithCompletion != NULL) {

This should be:

if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {

The problem with your original code is that ABAddressBookRequestAccessWithCompletion is not anything: it requires parameters, like you use later on in the same if statement. I am surprised you are not getting an error from Xcode. ABAddressBookGetAuthorizationStatus was new in iOS 6.

Also, you are supposed to create the Address Book Ref after you get permission, not before.

It is also possible that because the app was on your iPhone at some point, it remembers that you gave permission to the app to use your contacts. In the iOS simulator, there is a Reset Content and Settings option. This makes the simulator forget any permission settings you gave your app. I find it unlikely that you want to reset your iPhone, correct?

jzn
  • 656
  • 10
  • 17
erdekhayser
  • 6,537
  • 2
  • 37
  • 69
  • When I replace my if statement with yours I get a red warning in xcode of: Use of undeclared identifier 'ABAuthorizationStatusNotDetermined' – user3344977 Mar 10 '14 at 22:01
  • Edited my answer. Should have a `k` before (`kABAuthrorizationStatusNotDetermined`) – erdekhayser Mar 10 '14 at 22:08
  • You said "it remembers that you gave permission to the app to use your contacts." Wouldn't this be deleted/forgotten though by deleting the app and all of it's data from the iPhone? – user3344977 Mar 10 '14 at 22:21
  • It would seem like it should. However, if you try running your app on your phone and giving it permission to your address book, deleting the app, then running again, the app will not ask you for permission again. When iOS 7 first came out I remember seeing a place where you can see data left over from deleted apps, but cannot seem to recall just where I saw it – erdekhayser Mar 10 '14 at 22:34
  • Yeah I think I saw a tutorial on that yesterday, but it actually required you to do a full reset on your iPhone. Anyways, thanks for the help. – user3344977 Mar 10 '14 at 22:40
  • Sorry, but I took back the answer. By changing to your code, it screwed things up. Your code keeps the UIAlertView from popping up that asks the user to allow access to contacts. – user3344977 Mar 11 '14 at 18:11
  • That makes no sense. The code inside of this if statement should be the `ABAddressBookRequestAccessWithCompletion()`. The only thing that should have changed is the conditional, which should only occur the first time you ask for permission. After the user is asked once, you cannot ask again afterwards. If you reset the simulator, try it again to see if the alert comes up. – erdekhayser Mar 11 '14 at 22:02
  • I am not using the simulator, I am using a physical iPhone. The fact is, based on the code I provided, when I replaced "ABAddressBookRequestAccessWithCompletion != NULL" with your replacement of "ABAddressBookGetAuthorizationStatus == ABAuthorizationStatusNotDetermined", it somehow prevents the UIAlertView from popping up and asking for access. – user3344977 Mar 12 '14 at 00:26
  • Also, my code is based off an extremely popular answer from another address book access question that was asked back when iOS 6 first came out and it has 150+ up votes so I really don't know what else to tell you. – user3344977 Mar 12 '14 at 00:27
  • I have 3 apps currently using this framework, and I use my approach in each of them. I can show you my access code in a chat if you would like. If you have the link to the solution you found can you post the link? I'm intrigued. – erdekhayser Mar 12 '14 at 00:52
  • Sorry but i need to move onto other problems. It's not that I don't believe you, that just happens to not be working for me. I just went to look for the thread and it turns out you're right. The answer with 102 upvotes matches your way, the one I'm using is right below it with only 38 upvotes. Here's the question: http://stackoverflow.com/questions/12648244/programmatically-request-access-to-contacts – user3344977 Mar 12 '14 at 00:58
  • OH. I see what that answer you used was about. That was to support iOS 5 and iOS 6 at the same time. At this point, few developers still try supporting iOS 5, so that answer is semi-obsolete. – erdekhayser Mar 12 '14 at 01:08
  • Gotcha. I could have sworn I used the other one. Either way, looks like it's time to migrate to your solution. Thanks for all of the help. – user3344977 Mar 12 '14 at 01:14
  • @erdekhayser FYI the reason it wasn't working is that you were missing the () at the end of ABAddressBookGetAuthorizationStatus. Edited to add the empty parameters (), because otherwise XCode 5.1 will optimize out the line, treating the function call as a function pointer instead, and thus a comparison of two constants that are never equal. The result is the code in the if block is never executed. – jzn Apr 10 '14 at 16:29
2

I finally figured this out. Deleting an app and "all of it's data" is a misleading dialogue provided by your iPhone. In regards to testing with privacy settings, you have to go to Settings > General > Reset > Reset Location & Privacy. By doing this, you get a truly "fresh" environment that will allow you to test your "privacy access" code. Keep in mind that this will delete your location and privacy settings that you have set for all of the other apps you use.

user3344977
  • 3,584
  • 4
  • 32
  • 88
0

Use this code.....

if (ABAddressBookGetAuthorizationStatus == ABAuthorizationStatusNotDetermined){

instead of.....

 if (ABAddressBookRequestAccessWithCompletion != NULL) {
  • When I replace my if statement with yours I get a red warning in xcode of: Use of undeclared identifier 'ABAuthorizationStatusNotDetermined' – user3344977 Mar 10 '14 at 22:03