在Stackoverflow问题上(参见底部的“Source 1”),我在使用AddressBook时看到以下模式,其中程序员想要阻止主线程,直到用户授予(或拒绝)访问他/她的地址簿:
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);
dispatch_release(sema);
}
else { // we're on iOS 5 or older
accessGranted = YES;
}
if (accessGranted) {
NSArray *thePeople = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);
// Do whatever you need with thePeople...
}
但是根据文档(ABAddressBook Reference),完成处理程序在任意队列上执行,这意味着它可以在主队列上执行。如果完成处理程序放在主队列上,那么上面的代码将导致死锁。是否有任何文档保证完成处理程序不会放在主队列上?
ABAddressBook参考:“在任意队列上调用完成处理程序。如果您的应用程序在整个应用程序中使用通讯簿,您有责任确保将该通讯簿的所有用法分派到单个队列以确保正确的线程 - 安全操作。“
来源: