【问题标题】:Retrieve all contacts phone numbers in iOS检索 iOS 中的所有联系人电话号码
【发布时间】:2017-08-18 14:08:08
【问题描述】:

到目前为止,如果我显示一个选择器,我看到了获取多个电话号码的方法,以便用户可以选择人员然后获取电话号码。 我想要的是检索所有联系人的号码。 有没有可能?

【问题讨论】:

  • 您的应用是否授权用户共享联系人?
  • 是的,但那是另一回事,我知道我应该授予访问权限。

标签: ios objective-c contacts


【解决方案1】:

试试这个,它适用于 iOS 6 以及 iOS 5.0 或更早版本

Sample Project Demo

首先在Link Binary With Libraries

中添加以下框架
  • AddressBookUI.framework
  • AddressBook.framework

然后导入

#import <AddressBook/ABAddressBook.h>
#import <AddressBookUI/AddressBookUI.h>

然后使用下面的代码

请求访问通讯录的权限

ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);

__block BOOL accessGranted = NO;

if (&ABAddressBookRequestAccessWithCompletion != NULL) { // We are on iOS 6
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
        accessGranted = granted;
        dispatch_semaphore_signal(semaphore);
    });

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    dispatch_release(semaphore);
}

else { // We are on iOS 5 or Older
    accessGranted = YES;
    [self getContactsWithAddressBook:addressBook];
}

if (accessGranted) {
    [self getContactsWithAddressBook:addressBook];
}

从通讯录中检索联系人

// Get the contacts.
- (void)getContactsWithAddressBook:(ABAddressBookRef )addressBook {

    contactList = [[NSMutableArray alloc] init];
    CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
    CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);

    for (int i=0;i < nPeople;i++) {
        NSMutableDictionary *dOfPerson=[NSMutableDictionary dictionary];

        ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i);

        //For username and surname
        ABMultiValueRef phones =(__bridge ABMultiValueRef)((__bridge NSString*)ABRecordCopyValue(ref, kABPersonPhoneProperty));

        CFStringRef firstName, lastName;
        firstName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
        lastName  = ABRecordCopyValue(ref, kABPersonLastNameProperty);
        [dOfPerson setObject:[NSString stringWithFormat:@"%@ %@", firstName, lastName] forKey:@"name"];

        //For Email ids
        ABMutableMultiValueRef eMail  = ABRecordCopyValue(ref, kABPersonEmailProperty);
        if(ABMultiValueGetCount(eMail) > 0) {
            [dOfPerson setObject:(__bridge NSString *)ABMultiValueCopyValueAtIndex(eMail, 0) forKey:@"email"];

        }

        //For Phone number
        NSString* mobileLabel;

        for(CFIndex j = 0; j < ABMultiValueGetCount(phones); j++) {
            mobileLabel = (__bridge NSString*)ABMultiValueCopyLabelAtIndex(phones, j);
            if([mobileLabel isEqualToString:(NSString *)kABPersonPhoneMobileLabel])
            {
                [dOfPerson setObject:(__bridge NSString*)ABMultiValueCopyValueAtIndex(phones, j) forKey:@"phone"];
            }
            else if ([mobileLabel isEqualToString:(NSString*)kABPersonPhoneIPhoneLabel])
            {
                [dOfPerson setObject:(__bridge NSString*)ABMultiValueCopyValueAtIndex(phones, j) forKey:@"phone"];
                break ;
            }

        }
    [contactList addObject:dOfPerson];

    }
NSLog(@"Contacts = %@",contactList);
}

检索其他信息

// All Personal Information Properties
kABPersonFirstNameProperty;          // First name - kABStringPropertyType
kABPersonLastNameProperty;           // Last name - kABStringPropertyType
kABPersonMiddleNameProperty;         // Middle name - kABStringPropertyType
kABPersonPrefixProperty;             // Prefix ("Sir" "Duke" "General") - kABStringPropertyType
kABPersonSuffixProperty;             // Suffix ("Jr." "Sr." "III") - kABStringPropertyType
kABPersonNicknameProperty;           // Nickname - kABStringPropertyType
kABPersonFirstNamePhoneticProperty;  // First name Phonetic - kABStringPropertyType
kABPersonLastNamePhoneticProperty;   // Last name Phonetic - kABStringPropertyType
kABPersonMiddleNamePhoneticProperty; // Middle name Phonetic - kABStringPropertyType
kABPersonOrganizationProperty;       // Company name - kABStringPropertyType
kABPersonJobTitleProperty;           // Job Title - kABStringPropertyType
kABPersonDepartmentProperty;         // Department name - kABStringPropertyType
kABPersonEmailProperty;              // Email(s) - kABMultiStringPropertyType
kABPersonBirthdayProperty;           // Birthday associated with this person - kABDateTimePropertyType
kABPersonNoteProperty;               // Note - kABStringPropertyType
kABPersonCreationDateProperty;       // Creation Date (when first saved)
kABPersonModificationDateProperty;   // Last saved date

// All Address Information Properties
kABPersonAddressProperty;            // Street address - kABMultiDictionaryPropertyType
kABPersonAddressStreetKey;
kABPersonAddressCityKey;
kABPersonAddressStateKey;
kABPersonAddressZIPKey;
kABPersonAddressCountryKey;
kABPersonAddressCountryCodeKey;

Further Reference Read Apple Docs

更新: 你需要添加说明为什么你需要访问你Apps-Info.plist中的联系人

Privacy - Contacts Usage Description

<key>NSContactsUsageDescription</key>
<string>Write the reason why your app needs the contact.</string>

用于获取用户图像。

UIImage *contactImage;
if(ABPersonHasImageData(ref)){
 contactImage = [UIImage imageWithData:(__bridge NSData *)ABPersonCopyImageData(ref)];
}

注意:

AddressBook 框架在 iOS 9 中已弃用,取而代之的是经过改进的新 Contacts Framework

【讨论】:

  • getContactsWithAddressBook: 方法将在 iOS 5 中被调用两次。将 if 语句放入 iOS 6 代码中。那是合适的。
  • ABAddressBookRef addressBook = ABAddressBookCreate(); 已被贬低,可以改用ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL); (stackoverflow.com/questions/22800634/…) 谢谢 iccodebuster。
  • @tmr 谢谢你的更新...很快就会更新:)
  • 您在两个for 循环中使用i。这将导致跳过人员并至少导致崩溃。
  • 如果我没记错的话,这会泄漏大量的 CF 对象。 ABRecordCopyValue 之类的函数将返回对象的所有权转移给您,并且它们不会在任何地方释放。
【解决方案2】:
  • AddressBookUI.framework
  • AddressBook.framework

    这 2 个框架在 iOS 9 中已弃用

    --->苹果介绍

  • 联系框架
  • ContactUI 框架

Here 是使用最新框架上传的代码。

【讨论】:

  • 请从您的链接中添加您的代码,从您的回答来看,它并没有真正回答 OP 的问题,而只是提出建议。如果你这样做,我会考虑给你一个赞成票,因为这将非常有帮助,因为这里的答案已经被弃用了
【解决方案3】:

获取通讯录权限或通知用户需要更改其设置中的权限。

CGFloat iOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if(iOSVersion >= 6.0) {
        // Request authorization to Address Book
        addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
        if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
            ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
                //start importing contacts
                if(addressBookRef) CFRelease(addressBookRef);
            });
        }
        else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
            // The user has previously given access, add the contact
            //start importing contacts
            if(addressBookRef) CFRelease(addressBookRef);
        }
        else {
            // The user has previously denied access
            // Send an alert telling user to change privacy setting in settings app
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Unable to Access" message:@"Grant us access now!" delegate:self cancelButtonTitle:@"Not Now" otherButtonTitles:@"I'll Do It!", nil];
            [alert show];
            if(addressBookRef) CFRelease(addressBookRef);
        }
    } else {
        addressBookRef = ABAddressBookCreate();
        //start importing contacts
        if(addressBookRef) CFRelease(addressBookRef);
    }

获取记录

CFArrayRef records = ABAddressBookCopyArrayOfAllPeople(addressBook);
NSArray *contacts = (__bridge NSArray*)records;
CFRelease(records);

for(int i = 0; i < contacts.count; i++) {
    ABRecordRef record = (__bridge ABRecordRef)[contacts objectAtIndex:i];
}

获取电话号码

    ABMultiValueRef phonesRef    = ABRecordCopyValue(recordRef, kABPersonPhoneProperty);

    if(phonesRef) {
        count = ABMultiValueGetCount(phonesRef);
        for(int ix = 0; ix < count; ix++){
            CFStringRef typeTmp = ABMultiValueCopyLabelAtIndex(phonesRef, ix);
            CFStringRef numberRef = ABMultiValueCopyValueAtIndex(phonesRef, ix);
            CFStringRef typeRef = ABAddressBookCopyLocalizedLabel(typeTmp);

            NSString *phoneNumber = (__bridge NSString *)numberRef;
            NSString *phoneType = (__bridge NSString *)typeRef;


            if(typeTmp) CFRelease(typeTmp);
            if(numberRef) CFRelease(numberRef);
            if(typeRef) CFRelease(typeRef);
        }
        CFRelease(phonesRef);
    }

请注意,有些人的手机中有 20,000 个联系人。如果您打算这样做,您可能需要对进程进行多线程处理。

【讨论】:

    【解决方案4】:

    当然可以。首先,您需要获得用户这样做的权限。如果您不这样做,用户将不得不从设置中手动授权您的应用程序。有一个很好的例子说明如何检索所有电话号码、姓名、地址等'here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-23
      • 1970-01-01
      相关资源
      最近更新 更多