views:

6597

answers:

4

I am showing an addressbook view to the user and letting them click on a contact and select a phone number. If they select a phone number, I want to get the phone number as an integer and the contact's name as an NSString.

I've tried doing it with the following code:

    //printf("%s\n",[[(NSArray *)ABMultiValueCopyArrayOfAllValues(theProperty) objectAtIndex:identifier] UTF8String]);

 //CFArrayRef *arrayString = [[(NSArray *)ABMultiValueCopyArrayOfAllValues(theProperty) objectAtIndex:identifier] UTF8String];
 NSArray *arrayString = [(NSArray *)ABMultiValueCopyArrayOfAllValues(theProperty) objectAtIndex:identifier];
 printf("%s\n", arrayString);

This code is inside this method:

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

And I am checking if the user selected a phone number with this code:

if (propertyType == kABStringPropertyType)   
{
 [self wrongSelection];

} 
else if (propertyType == kABIntegerPropertyType)  
{
 [self wrongSelection];

} 
else if (propertyType == kABRealPropertyType)  
{
 [self wrongSelection];
} 
else if (propertyType == kABMultiStringPropertyType)     
{
     //This is the phone number...

I am able to get the phone number to display in the console with printf, however I can't figure out how to convert it into an integer and how to also get the contacts name even though the property selected is not a person's name.

Also, what I'm doing seems very inefficient. Are there any better ways to do this?

Edit: If I can't store them as an int, a string would be fine. I just can't figure out how to go from that array to an actual string. If I cast it or save it as a UTF8String I always get some error.

A: 

You can't convert the phone number into an integer. Phone numbers are strings. The default entry Apple includes for itself has the number "1-800-MYAPPLE".

Also, even if all components of a phone number are digits, there is no guarantee that phone numbers in all parts of the world are actually small enough to fit inside a 64 bit value, once you factor in area codes, country codes, internal extensions, etc. Users are free to put as much as they want in there.

Louis Gerbarg
+3  A: 

To get the property efficiently (as far as reading goes), you can do something like this in your callback method:

switch( propertyType ) {
  case kABMultiStringPropertyType:
    // this is the phone number, do something
    break;
  default:
    [self wrongSelection];
    break;
}

I'm not sure you actually even need to parse that, though. To get the phone number from the record you could do (again, inside your callback method):

ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSArray* phoneNumbers = (NSArray*)ABMultiValueCopyArrayOfAllValues(phoneNumberProperty);
CFRelease(phoneNUmberProperty);

// Do whatever you want with the phone numbers
NSLog(@"Phone numbers = %@", phoneNumbers);
[phoneNumbers release];
Jason Coco
+2  A: 
CFStringRef cfName = ABRecordCopyCompositeName(person);
NSString *personName = [NSString stringWithString:(NSString *)cfName];
CFRelease(cfName);

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

contactString contains the phone number selected, and personName contains the person's name. As stated above, you can't necessarily convert the string to numbers generically, as it may contain alphabetic characters. However, you could write your own handler to convert alphabetic characters to numbers and strip out everything else to get a numeric string only, which you could then convert to a long (phone numbers get pretty long) .

I question the need to convert a phone number to a numeric value, though, since it may also contain other necessary characters like Pause. Also, a phone number represents a string of digits more than it represents one long number anyway, so the conceptual data format is more String than Int in any case.

Ed Marty
Just ran into a problem with this code. ABMultiValueCopyValueAtIndex(container, identifier) is expecting an index rather than the identifier. This will crash intermittently. The code should be ABMultiValueCopyValueAtIndex(container, ABMultiValueGetIndexForIdentifier(container, identifier)). See this forum post: http://forums.macrumors.com/showthread.php?t=705504
Maha
A: 

Another reason not to use integers - some countries use leading zeros on phone numbers, e.g. all UK numbers start with a zero (usually written 01234 567890 or 0123 4567890)!

Dan J