Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ABAddressBookRequestAccessWithCompletion iOS 7 and semaphores

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);
}
like image 409
mickm Avatar asked Nov 20 '25 05:11

mickm


1 Answers

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)..

like image 98
david-hoze Avatar answered Nov 21 '25 17:11

david-hoze



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!