【问题标题】:Fetch Contacts in iOS 7在 iOS 7 中获取联系人
【发布时间】:2013-10-02 08:31:50
【问题描述】:

此代码适用于 iOS5/iOS6,但不适用于 iOS7。

CFErrorRef *error = NULL;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
    //ABAddressBookRef addressBook = ABAddressBookCreate();
    CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
    CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);

    for(int i = 0; i < numberOfPeople; i++) {

        ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );

        NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
        NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
     //   NSLog(@"Name:%@ %@", firstName, lastName);

        ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
        NSString *phoneNumber;
        for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
            phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
            //   NSLog(@"phone:%@", phoneNumber);
        }

【问题讨论】:

  • 在 iOS 7 上会发生什么
  • CFArrayRef 不返回数组。总是返回一个空数组
  • 你是在模拟器上还是在设备上测试?我注意到 iOS 模拟器默认没有联系人。当我添加一个时,很明显该代码确实适用于 iOS 6 和 7。
  • 帕斯克,你是对的!难以置信,但只有在更新到 XCODE 5.0.2 之后,模拟器的通讯录是空的!之前,您始终可以使用标准联系人“John Appleseed”等测试您的应用程序。现在您必须在每次重置模拟器时手动插入自己的地址!
  • 我在这里发布了 Swift 版本:stackoverflow.com/a/33219114/745161

标签: iphone ios ipad ios7


【解决方案1】:

今天更新了我的示例并删除了内存泄漏:)

 + (NSArray *)getAllContacts {

    CFErrorRef *error = nil;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
    ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
    CFArrayRef allPeople = (ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName));
    //CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
      CFIndex nPeople = CFArrayGetCount(allPeople); // bugfix who synced contacts with facebook
    NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople];

    if (!allPeople || !nPeople) {
        NSLog(@"people nil");
    }


    for (int i = 0; i < nPeople; i++) {

        @autoreleasepool {

            //data model
            ContactsData *contacts = [ContactsData new];

            ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);

            //get First Name
            CFStringRef firstName = (CFStringRef)ABRecordCopyValue(person,kABPersonFirstNameProperty);
            contacts.firstNames = [(__bridge NSString*)firstName copy];

            if (firstName != NULL) {
                CFRelease(firstName);
            }


            //get Last Name
            CFStringRef lastName = (CFStringRef)ABRecordCopyValue(person,kABPersonLastNameProperty);
            contacts.lastNames = [(__bridge NSString*)lastName copy];

            if (lastName != NULL) {
                CFRelease(lastName);
            }


            if (!contacts.firstNames) {
                contacts.firstNames = @"";
            }

            if (!contacts.lastNames) {
                contacts.lastNames = @"";
            }



            contacts.contactId = ABRecordGetRecordID(person);
            //append first name and last name
            contacts.fullname = [NSString stringWithFormat:@"%@ %@", contacts.firstNames, contacts.lastNames];


            // get contacts picture, if pic doesn't exists, show standart one
            CFDataRef imgData = ABPersonCopyImageData(person);
            NSData *imageData = (__bridge NSData *)imgData;
            contacts.image = [UIImage imageWithData:imageData];

            if (imgData != NULL) {
                CFRelease(imgData);
            }

            if (!contacts.image) {
                contacts.image = [UIImage imageNamed:@"avatar.png"];
            }


            //get Phone Numbers
            NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
            ABMultiValueRef multiPhones = ABRecordCopyValue(person, kABPersonPhoneProperty);

            for(CFIndex i=0; i<ABMultiValueGetCount(multiPhones); i++) {
                @autoreleasepool {
                    CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
                    NSString *phoneNumber = CFBridgingRelease(phoneNumberRef);
                    if (phoneNumber != nil)[phoneNumbers addObject:phoneNumber];
                    //NSLog(@"All numbers %@", phoneNumbers);
                }
            }

            if (multiPhones != NULL) {
                CFRelease(multiPhones);
            }

            [contacts setNumbers:phoneNumbers];

            //get Contact email
            NSMutableArray *contactEmails = [NSMutableArray new];
            ABMultiValueRef multiEmails = ABRecordCopyValue(person, kABPersonEmailProperty);

            for (CFIndex i=0; i<ABMultiValueGetCount(multiEmails); i++) {
                @autoreleasepool {
                    CFStringRef contactEmailRef = ABMultiValueCopyValueAtIndex(multiEmails, i);
                    NSString *contactEmail = CFBridgingRelease(contactEmailRef);
                    if (contactEmail != nil)[contactEmails addObject:contactEmail];
                    // NSLog(@"All emails are:%@", contactEmails);
                }
            }

            if (multiEmails != NULL) {
                CFRelease(multiEmails);
            }

            [contacts setEmails:contactEmails];

            [items addObject:contacts];

#ifdef DEBUG
            //NSLog(@"Person is: %@", contacts.firstNames);
            //NSLog(@"Phones are: %@", contacts.numbers);
            //NSLog(@"Email is:%@", contacts.emails);
#endif

        }
    } //autoreleasepool
    CFRelease(allPeople);
    CFRelease(addressBook);
    CFRelease(source);
    return items;

}

实际上最近使用 CNContacts 在 Swift 3 中编写了 pod,可能需要它

Swift ContactBook Picker

【讨论】:

  • @DipakSonara 我只是举了个例子。不是我所有的工作代码。但它正在工作并通过图片、电话和电子邮件获取我所有的联系人。您已经创建了一个仅包含一个联系人的数组。然后进行迭代。无论如何,请参阅我的更新答案
  • 我得到了解决方案,实际上我们需要获得用户的许可。 stackoverflow.com/questions/12648244/…
  • @DipakSonara 是的,没错。同样的解决方案也在我上面的代码中。 ABAddressBookRequestAccessWithCompletion
  • ContactsData 是如何定义的?
  • @TravMcKinney ContactsData 是我的 Class 实例。 interface ContactsData : NSObject 属性(强,非原子) NSMutableArray numbers;属性(强,非原子) NSMutableArray *emails;属性(强,非原子) UIImage 图像;属性(强,非原子) NSString *firstNames;属性(强,非原子) NSString *lastNames;
【解决方案2】:

不是我自己写的。但它适用于我:

ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);

if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
    ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
       ABAddressBookRef addressBook = ABAddressBookCreate( );
    });
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {

    CFErrorRef *error = NULL;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
    CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
    CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);

    for(int i = 0; i < numberOfPeople; i++) {

        ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );

       // NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
       // NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
       // NSLog(@"Name:%@ %@", firstName, lastName);

        ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
        [[UIDevice currentDevice] name];

        //NSLog(@"\n%@\n", [[UIDevice currentDevice] name]);

        for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
            NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);

            addressBookNum = [addressBookNum stringByAppendingFormat: @":%@",phoneNumber];
        }  
    }
    NSLog(@"AllNumber:%@",addressBookNum);
}
else {
    // Send an alert telling user to change privacy setting in settings app
}

在我的 .h 中

@property NSString * addressBookNum;

【讨论】:

  • 非常感谢老兄
  • @SampathKumar 在我看来像个淑女
  • 这里有很多内存泄漏。不要忘记 CFRelease() 。无论如何它可以工作,我已经使用了这个代码(修复了泄漏)。谢谢 CMD + shift + b :)
猜你喜欢
  • 1970-01-01
  • 2016-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-26
  • 1970-01-01
  • 2019-11-28
  • 2016-09-11
相关资源
最近更新 更多