下面是我的一些代码,它在将联系人加载到tableview时不会阻塞主线程。它似乎工作正常但我想知道在if(accessGranted)之后调用dispatch_async之后这是否最终会导致一些erradic行为。如果我正在做的是良好的做法,那么也许这会对一些人有所帮助,因为我看到很多人对AB有许多不同答案的问题(可能是因为AB的记录很差)但如果不是那么希望有人可以告诉我,我做错了什么。
我的理解是,这将是线程安全的,因为它是在同一个线程上完成的。
CFErrorRef error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6 or later
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;
}
if (accessGranted) {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
CFArrayRef contacts = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFMutableArrayRef peopleMutable = CFArrayCreateMutableCopy(kCFAllocatorDefault,
CFArrayGetCount(contacts),
contacts);
CFArraySortValues(peopleMutable,
CFRangeMake(0, CFArrayGetCount(peopleMutable)),
(CFComparatorFunction) ABPersonComparePeopleByName,
kABPersonSortByFirstName);
CFRelease(contacts);
for (CFIndex i = 0; i < CFArrayGetCount(peopleMutable); i++)
{
ABRecordRef record = CFArrayGetValueAtIndex(peopleMutable, i);
ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(record, kABPersonPhoneProperty);
if (CFBridgingRelease(ABMultiValueCopyValueAtIndex(phoneNumberProperty, 0)) != nil) {
NSString *firstName = CFBridgingRelease(ABRecordCopyValue(record, kABPersonFirstNameProperty));
NSString *lastName = CFBridgingRelease(ABRecordCopyValue(record, kABPersonLastNameProperty));
NSString *phoneNumbers = (__bridge NSString*)ABMultiValueCopyValueAtIndex(phoneNumberProperty, 0);
}
CFRelease(phoneNumberProperty);
}
CFRelease(peopleMutable);
dispatch_async(dispatch_get_main_queue(), ^{
// Update UI
[self.tableView reloadData];
});
});
}