この質問に対して私が見たほとんどの回答は、GCDで非常に複雑なことを行い、メインスレッドをブロックすることになります。それは必要はありません!
これが私が使用しているソリューションです(iOS5とiOS6で動作します):
- (void)fetchContacts:(void (^)(NSArray *contacts))success failure:(void (^)(NSError *error))failure {
if (ABAddressBookRequestAccessWithCompletion) {
// on iOS 6
CFErrorRef err;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &err);
if (err) {
// handle error
CFRelease(err);
return;
}
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
// ABAddressBook doesn't gaurantee execution of this block on main thread, but we want our callbacks to be
dispatch_async(dispatch_get_main_queue(), ^{
if (!granted) {
failure((__bridge NSError *)error);
} else {
readAddressBookContacts(addressBook, success);
}
CFRelease(addressBook);
});
});
} else {
// on iOS < 6
ABAddressBookRef addressBook = ABAddressBookCreate();
readAddressBookContacts(addressBook, success);
CFRelease(addressBook);
}
}
static void readAddressBookContacts(ABAddressBookRef addressBook, void (^completion)(NSArray *contacts)) {
// do stuff with addressBook
NSArray *contacts = @[];
completion(contacts);
}