在 Stackoverflow 问题上(请参阅底部的“源 1”),我在使用 AddressBook 时看到以下模式,其中程序员希望阻止主线程,直到用户授予(或拒绝)访问他/她的 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...
}
但根据文档(ABAAddressBook Reference),完成处理程序在任意队列上执行,这意味着它可以在主队列上执行。如果完成处理程序放在主队列上,那么上面的代码将导致死锁。是否有任何文档保证完成处理程序不会放在主队列中?
ABAddressBook 参考:“在任意队列上调用完成处理程序。如果您的应用程序在整个应用程序中使用地址簿,您有责任确保将该地址簿的所有使用分派到单个队列,以确保正确的线程安全操作。”
资源: