3

this code has been posted before, and been used as well, from what i could gather. i'm in a situation where i need the code to NOT continue until i know if i have access to the contacts.

on Xcode 5.0.2 and iOS 6, this works just fine. on iOS 7, it hangs forever, and then when i kill the app the dialog box comes up asking to allow access to the contacts.

ABAddressBookRef addressBook = ABAddressBookCreate();

__block BOOL accessGranted = NO;

if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
dispatch_semaphore_t sema = dispatch_semaphore_create(0);

ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
    accessGranted = granted;
    dispatch_semaphore_signal(sema);
});

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

in trying to play with this, i then simply set a BOOL to be NO, and then set it to YES within the block. after the block, i put a while loop that checked for the variable being YES, then slept for 1 second. works perfectly fine on 6, on 7 i never reach the NSLog statement in the block, and i'm stuck forever in the while loop printing the log statement.

am i doing something really lame here? or is this method gone haywire on 7?

ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
    if (granted)
    {
        self.myAddressBook = addressBook;
    }

    done = YES;
    NSLog(@"in block, done is %@", done ? @"YES" : @"NO");
    didGrant = granted;

    //dispatch_semaphore_signal(sema);
});

while (!done)
{
    NSLog(@"done is %@", done ? @"YES" : @"NO");
    sleep(1);
}
mickm
  • 515
  • 2
  • 11
  • 20

1 Answers1

5

I had the same problem, and I realised that the Dialog box that requests access to the contacts blocks the app anyways, so maybe there's a deadlock. So I just ditched the semaphores and did something like this (tested and works on iOS 7.1.1):

ABAddressBookRef addressBook = ABAddressBookCreate();

MyController * __weak weakSelf = self;

if (ABAddressBookRequestAccessWithCompletion != NULL)
{ // we're on iOS 6
    if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
    {
        ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [weakSelf accessGrantedForAddressBook];
            });
        });    
    }
    else
        if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized); //Maybe add something here to handle kABAuthorizationStatusRestricted
            [self accessGrantedForAddressBook];
    }
}
else // we're on iOS 5 or older
     [self accessGrantedForAddressBook];

which is quite similar to what Apple does in their documentation (search for ABAddressBookRequestAccessWithCompletion). Besides, what's the point of ABAddressBookRequestAccessWithCompletion being asynchronous and waiting for it (see here)..

Community
  • 1
  • 1
david-hoze
  • 1,045
  • 15
  • 31