ios - ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering 不工作

标签 ios objective-c ios7 ios8 abaddressbook

ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);

__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;
}

if (accessGranted) {

//  ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
    ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
    CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName);
    CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
    NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople];
}

我使用此代码获取所有联系人,但 ABAddressBookGetPersonCount 工作正常,但 ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering 不工作。

最佳答案

几个问题:

  1. 您可以简化获取人员数组的过程,例如:

    if (accessGranted) {
        ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
        NSArray *allPeople = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName));
        NSUInteger nPeople = [allPeople count];
    
        // do what you want with the array
    
        // don't forget to release `source`; because we bridged allPeople, ARC will take care of that
    
        CFRelease(source);
    }
    
  2. 您很可能没有正确捕获打开错误。应该是:

    CFErrorRef error = NULL;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
    if (!addressBook) {
        NSLog(@"Error opening address book: %@", CFBridgingRelease(error));
        return;
    }
    

    注意,你要避免的是

    CFErrorRef *error = NULL;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
    

    您偶尔会在 Stack Overflow 上看到这种模式,但它是不正确的。这永远不会返回错误对象。

  3. 您不应该使用那样的信号量,因为您在等待用户第一次授予权限时会阻塞主线程。如果您在错误的时间这样做,看门狗进程可能会终止您的应用。

    相反,采用异步模式,将在用户授予权限后应运行的代码放在 ABAddressBookRequestAccessWithCompletion 调用的完成 block 参数中。但切勿将信号量与此异步权限 API 结合使用。

  4. 您可能已经知道如何执行此操作,但是例如,要获取人员的姓名,您可以执行以下操作:

    for (NSInteger i = 0; i < nPeople; i++) {
        ABRecordRef person = (__bridge ABRecordRef)allPeople[i];
        NSString *firstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
        NSString *lastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
        NSLog(@"%@ %@", firstName, lastName);
    }
    
  5. 记得通过静态分析器运行代码(shift+command+B,或者 Xcode 的“Analyze” Product"菜单),它非常擅长识别代码中可能困扰地址簿代码的漏洞。

    请记住“Create Rule”,即任何时候调用名称中带有CreateCopy 的Core Foundation 函数时,您有责任释放对象,调用 CFRelease 或使用 CFBridgingRelease(或 __bridge_transfer)将所有权转移给 ARC。

关于ios - ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28230131/

相关文章:

objective-c - 由于保留或其他原因导致的泄漏? ( Objective-C )

ios - 如何下载 Swift Playgrounds iPad 应用程序?

ios - 为通知创建委托(delegate)

objective-c - 刷新整个 NSFetchedResultsController tableView

autolayout - iOS Auto Layout与Springs&Struts

ios - 由于我的 'NSInvalidArgumentException' 中的未捕获异常 "game"而终止应用程序

ios - iPad 上的 iOS 10.1.1 应用商店拒绝 iPhone 应用

ios - 以编程方式关注创建为 AccessoryView 的 UITextView

ios7 - 栏按钮未显示在工具栏xcode 5上

ios - 检查 NSString 是否有负 bool 值