tags:

views:

2206

answers:

4

All I want to do is let the user select a number from the address book. I found the code in this question:

http://stackoverflow.com/questions/286207/how-to-get-a-phone-number-from-an-address-book-contact-iphone-sdk

ABMultiValueRef container = ABRecordCopyValue(person, property);
CFStringRef contactData = ABMultiValueCopyValueAtIndex(container, identifier);
CFRelease(container);
NSString *contactString = [NSString stringWithString:(NSString *)contactData];
CFRelease(contactData);

The problem is that on the second line (when running on a 3.0 device) I get the following error:

Account Manager could not find account with identifier MobileMe:rustyshelf

followed by:

Program received signal: "EXC_BAD_ACCESS".

This is all inside the picker delegate method:

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

This is just one of the contacts in my address book, which is synched with Mobile Me

Edit: I think this might be a bug with the SDK, it happens for some of my contacts but not for others...

+1  A: 

You should be able to just do the following:

ABMultiValueRef phoneNumbers = (ABMultiValueRef)ABRecordCopyValue(person, kABPersonPhoneProperty);
CFRelease(phoneNumbers);
NSString* phoneNumber = (NSString*)ABMultiValueCopyValueAtIndex(phoneNumbers, 0);

Of course, that's only going to get you the first number of (potentially) many associated with the person who's been selected.

Nathan de Vries
thanks for the answer, but I just want to find the number that the user clicked on. I think my code is correct, but it sounds like there's a bug in firmware 3.0 stopping me from getting it. The code above works for some of my contacts, but not for others.
rustyshelf
+2  A: 

I use this to pull the mobile number from an ABRecordRef/ The "record" variable is the ABRecordRef you want the phone number for. Where I have "" you can use another phone tag string to find other types of phone numbers.

//Get mobile phone number
ABMultiValueRef phones =(NSString*)ABRecordCopyValue(record, kABPersonPhoneProperty);
NSString* mobile=@"";
NSString* mobileLabel;
for(CFIndex i = 0; i < ABMultiValueGetCount(phones); i++) {
    mobileLabel = (NSString*)ABMultiValueCopyLabelAtIndex(phones, i);
    if([mobileLabel isEqualToString:@"_$!<Mobile>!$_"]) {
          mobile = (NSString*)ABMultiValueCopyValueAtIndex(phones, i);
    }
}
JWD
Wouldn't that code fail to find mobile numbers that are tagged with the 'iPhone' tag. In Australia at least that seems to happen automatically for contacts received via MMS.
rustyshelf
You are right, the code I posted is just searching for the numbers tagged "_$!<Mobile>!$_". It is also looping over all results in the for loop, so you could easily change "_$!<Mobile>!$_" to "iPhone" and it should work.
JWD
+3  A: 

The "identifier" argument does not hold the CFIndex of the record touched. The method I use to tell which phone number a user selected is this:

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
    if (property == kABPersonPhoneProperty) {
     ABMultiValueRef multiPhones = ABRecordCopyValue(person, kABPersonPhoneProperty);
     for(CFIndex i = 0; i < ABMultiValueGetCount(multiPhones); i++) {
      if(identifier == ABMultiValueGetIdentifierAtIndex (multiPhones, i)) {
       CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
       CFRelease(multiPhones);
       NSString *phoneNumber = (NSString *) phoneNumberRef;
       CFRelease(phoneNumberRef);
       txtPhoneNumber.text = [NSString stringWithFormat:@"%@", phoneNumber];
       [phoneNumber release];
      }
     }
    }

    [self dismissModalViewControllerAnimated:YES];
    return NO;
}
+2  A: 

Going off of JWDs answer, here is a safer version that uses the builtin constants and chooses the iphone number over another mobile number...

ABMultiValueRef phones =(NSString*)ABRecordCopyValue(person, kABPersonPhoneProperty);
NSString* mobile=@"";
NSString* mobileLabel;
for(CFIndex i = 0; i < ABMultiValueGetCount(phones); i++) {
 mobileLabel = (NSString*)ABMultiValueCopyLabelAtIndex(phones, i);
 if([mobileLabel isEqualToString:(NSString *)kABPersonPhoneMobileLabel])
 {
  [mobile release] ;
  mobile = (NSString*)ABMultiValueCopyValueAtIndex(phones, i);
 }
 else if ([mobileLabel isEqualToString:(NSString*)kABPersonPhoneIPhoneLabel])
 {
  [mobile release] ;
  mobile = (NSString*)ABMultiValueCopyValueAtIndex(phones, i);
  break ;
 }
}
dr_pepper