iOS 6 address book empty kABPersonPhoneProperty

2019-03-29 05:48发布

问题:

In my code I use ABPeoplePickerNavigationController to select person. After user select person from contact list, I look if specified person record have any phone number:

- (BOOL) peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {
      ABMutableMultiValueRef phones;
      phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
      if (phones == nil || ABMultiValueGetCount(phones) == 0)
      {
          return NO;
      }
      // other code....
}

I created contact, added phone number to it and tested my code. In iOS 5 this code works well. phones variable contains one phone number.

But in iOS 6, after linking contact to facebook account, phones variable doesn't contain any values.

After unlinking contact with facebook account everything works well again.

How can I read person phone numbers this method?

- (BOOL) peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person

UPD

If i return YES in the function above, then in function

 (BOOL) peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier

I can read all person phone numbers in normal way. So why I can't read them in the first function?

回答1:

I found the answer to my question. If the contact is linked, then in method

- (BOOL) peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person

you recieve a reference to person, which respesents a linked contact. To retrieve all phone numbers you need to get all linked contacts and then look for phone numbers in that contacts. I do this with the following code:

- (BOOL) peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{

ABMutableMultiValueRef phones;
phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
if (phones == nil || ABMultiValueGetCount(phones) == 0)
{
    CFArrayRef linkedContacts = ABPersonCopyArrayOfAllLinkedPeople(person);
    phones = ABMultiValueCreateMutable(kABPersonPhoneProperty);
    ABMultiValueRef linkedPhones;
    for (int i = 0; i < CFArrayGetCount(linkedContacts); i++)
    {
        ABRecordRef linkedContact = CFArrayGetValueAtIndex(linkedContacts, i);
        linkedPhones = ABRecordCopyValue(linkedContact, kABPersonPhoneProperty);
        if (linkedPhones != nil && ABMultiValueGetCount(linkedPhones) > 0)
        {
            for (int j = 0; j < ABMultiValueGetCount(linkedPhones); j++)
            {
                ABMultiValueAddValueAndLabel(phones, ABMultiValueCopyValueAtIndex(linkedPhones, j), NULL, NULL);
            }
        }
        CFRelease(linkedPhones);
    }
    CFRelease(linkedContacts);

    if (ABMultiValueGetCount(phones) == 0)
    {
        CFRelease(phones);
        return NO;
    }   
}
// other code ...

}

With that code i received all phone numbers for linked contact.



回答2:

In the solution re: linked contacts you need to change the line which stores the phone numbers found to

ABMultiValueAddValueAndLabel(phones, ABMultiValueCopyValueAtIndex(linkedPhones, j),
    ABMultiValueCopyLabelAtIndex(linkedPhones, j), NULL);

so that you can use the 'phones' to check by label later. The solution given just stores the numbers so you would not be able to test against constants like kABPersonPhoneMainLabel

This approach is also used for emails and addresses. For addresses you pull out the parts like this:-

CFDictionaryRef dict = ABMultiValueCopyValueAtIndex(address, 0);
street.text = CFBridgingRelease(CFDictionaryGetValue(dict, kABPersonAddressStreetKey));