15

So I have a method to get all the contact phone numbers from the address book on the iPhone, but is there a way to get the phone number label? For example you can do this: enter image description here

And I'd be looking to modify my method to print out the label (such as iPhone/Home/mobile/etc).

ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef all = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex n = ABAddressBookGetPersonCount(addressBook);

for( int i = 0 ; i < n ; i++ )
{
    ABRecordRef ref = CFArrayGetValueAtIndex(all, i);
    NSString *firstName = (NSString *)ABRecordCopyValue(ref, kABPersonFirstNameProperty);
    NSLog(@"Name %@", firstName);

    ABMultiValueRef *phones = ABRecordCopyValue(ref, kABPersonPhoneProperty);
    for(CFIndex j = 0; j < ABMultiValueGetCount(phones); j++)
    {
        NSString *phoneLabel = @""; // ???

        CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phones, j);
        //CFRelease(phones);
        NSString *phoneNumber = (NSString *)phoneNumberRef;
        CFRelease(phoneNumberRef);
        NSLog(@"  - %@ (%@)", phoneNumber, phoneLabel);
        [phoneNumber release];
    }
}
ingh.am
  • 24,319
  • 41
  • 126
  • 176

4 Answers4

60

Simply use -

ABMultiValueRef phones = ABRecordCopyValue(ref, kABPersonPhoneProperty);
for(CFIndex j = 0; j < ABMultiValueGetCount(phones); j++)
{
  CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phones, j);
  CFStringRef locLabel = ABMultiValueCopyLabelAtIndex(phones, j);
  NSString *phoneLabel =(NSString*) ABAddressBookCopyLocalizedLabel(locLabel);
  //CFRelease(phones);
  NSString *phoneNumber = (NSString *)phoneNumberRef;
  CFRelease(phoneNumberRef);
  CFRelease(locLabel);
  NSLog(@"  - %@ (%@)", phoneNumber, phoneLabel);
  [phoneNumber release];
}

EDIT Please see the notes for this answer about CFBridgingRelease and __bridge_transfer.

Inder Kumar Rathore
  • 37,431
  • 14
  • 121
  • 176
shannoga
  • 19,000
  • 20
  • 99
  • 163
  • 3
    Instead of using (NSString *) to cast to string use (__bridge_transfer NSString*). – Dev2rights Feb 05 '13 at 15:28
  • You can also use `id CFBridgingRelease( CFTypeRef )` and its complement `CFTypeRef CFBridgingRetain( id )`. – devios1 Aug 02 '13 at 06:51
  • Also I'm pretty sure you don't want to call `CFRelease` on those after calling `CFBridgingRelease` (or `__bridge_transfer`), as the whole point of doing so is to transfer responsibility of releasing to the Objective-C object. – devios1 Aug 02 '13 at 07:01
  • Thx! That helped me! :) – Vladimir May 12 '14 at 11:21
  • DO you have any idea how i can fix this error? `error: cannot initialize a variable of type 'CFStringRef' (aka 'const __CFString *') with an rvalue of type 'CFTypeRef' (aka 'const void *') ...CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phones, j);` – Fouad Sep 24 '14 at 22:09
  • Isn't there a `CFRelease(phones);` missing after the for loop? – newenglander Apr 02 '16 at 14:50
3
//get the particular contact or email from phone book

    - (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)picker shouldContinueAfterSelectingPerson:(ABRecordRef)person
    {
        // Name of contact.

        NSString* name = (NSString *)ABRecordCopyCompositeName(person);

        // Numbers of selected contact

        ABMutableMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);

        NSMutableString *mobile = [[NSMutableString alloc] init];
        NSMutableString *office = [[NSMutableString alloc] init];

        // Getting if Mobile, Office(work) numbers exist

        for(CFIndex numberIndex = 0; numberIndex < ABMultiValueGetCount(phones); numberIndex++)
        {
            // Number in contact details of current index

        CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phones, numberIndex);

        // Label of Phone Number

        CFStringRef locLabel = ABMultiValueCopyLabelAtIndex(phones, numberIndex);
        NSString *phoneLabel =(NSString*) ABAddressBookCopyLocalizedLabel(locLabel);

        // Phone number

        NSString *phoneNumber = (NSString *)phoneNumberRef;

        // Release Phone Number and locationLabel reference object

        CFRelease(phoneNumberRef);
        CFRelease(locLabel);

        NSLog(@"  - %@ (%@)", phoneNumber, phoneLabel);

        if ([phoneLabel isEqualToString:NSLocalizedString(@"mobile", nil)])// Mobile number saving.
        {
            [mobile appendFormat:@"%@", phoneNumber];
        }
        else if ([phoneLabel isEqualToString:NSLocalizedString(@"work", nil)])// Office number saving.
        {
            [office appendFormat:@"%@", phoneNumber];
        }

        [phoneNumber release];
    }
    CFRelease(phones);

    // Emails of selected contact

    ABMutableMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);

    NSMutableString *generalMail = [[NSMutableString alloc] init];
    NSMutableString *officeMail = [[NSMutableString alloc] init];

    // Getting if Home, Office(work) mails exist

    for(CFIndex numberIndex = 0; numberIndex < ABMultiValueGetCount(emails); numberIndex++)
    {
        // Mail in contact details of current index

        CFStringRef mailRef = ABMultiValueCopyValueAtIndex(emails, numberIndex);

        // Label of Phone Number

        CFStringRef locLabel = ABMultiValueCopyLabelAtIndex(emails, numberIndex);
        NSString *mailLabel =(NSString*) ABAddressBookCopyLocalizedLabel(locLabel);

        // Phone number

        NSString *mail = (NSString *)mailRef;

        // Release Phone Number and locationLabel reference object

        CFRelease(mailRef);
        CFRelease(locLabel);
        NSLog(@"  - %@ (%@)", mail, mailLabel);

        if ([mailLabel isEqualToString:NSLocalizedString(@"mobile", nil)])// Home mail.
        {
            [generalMail appendFormat:@"%@", mail];
        }
        else if ([mailLabel isEqualToString:NSLocalizedString(@"work", nil)])// Office(Work) mail.
        {
            [officeMail appendFormat:@"%@", mail];
        }

        [mail release];
    }
    CFRelease(emails);

    [mobile release];
    [office release];

    [generalMail release];
    [officeMail release];

    [self dismissViewControllerAnimated:YES completion:nil];
    return NO;
}
Kaushik Movaliya
  • 729
  • 10
  • 26
abhi
  • 507
  • 6
  • 9
  • if this code runs with deutsch, then "mobile" turns "mobil"! . How can I handle such cases? I may not able to check for all strings – BaSha Nov 17 '14 at 12:12
  • Ok. Create localize file in your project for which language you want. In that file define mobile = 'mpbiel'. I am modifying according to that above code. – abhi Dec 04 '14 at 06:05
  • Actually I had solved issue, We need to compare local label instead localized label -> let locLabel : CFStringRef = ABMultiValueCopyLabelAtIndex(phones, numberIndex).takeUnretainedValue() as CFStringRef; if (String(locLabel) == String(kABHomeLabel)){} – BaSha Dec 04 '14 at 09:01
0

If you are adding records to the AddressBook, these predefined constants may be what you want, kABPersonPhoneMobileLabel, kABPersonPhoneIPhoneLabel, which are defined in the file ABPerson.h.

DawnSong
  • 3,232
  • 1
  • 26
  • 35
-4

the following should help:

NSArray* AccountEmailAddresses(void)
{
    NSMutableArray *emailAddresses = [NSMutableArray array];
    @try
    {
        Class MailComposeController = NSClassFromString(@"MailComposeController") ?: NSClassFromString(@"MFMailComposeController");
        NSArray *accountEmailAddresses = [MailComposeController performSelector:@selector(accountEmailAddresses)];
        for (id address in accountEmailAddresses)
        {
            if ([address isKindOfClass:[NSString class]])
                [emailAddresses addObject:address];
        }
    }
    @catch (NSException *e) {}

    return [NSArray arrayWithArray:emailAddresses];
}


ABRecordRef ABGetMe(ABAddressBookRef addressBook)
{
    ABRecordRef me = NULL;
    NSArray *accountEmailAddresses = AccountEmailAddresses();
    CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
    CFIndex peopleCount = CFArrayGetCount(people);
    for (CFIndex i = 0; i < peopleCount; i++)
    {
        ABRecordRef record = CFArrayGetValueAtIndex(people, i);
        ABMultiValueRef emails = ABRecordCopyValue(record, kABPersonEmailProperty);
        if (emails)
        {
            CFIndex emailCount = ABMultiValueGetCount(emails);
            for (CFIndex j = 0; j < emailCount; j++)
            {
                CFStringRef email = ABMultiValueCopyValueAtIndex(emails, j);
                if (email)
                {
                    if ([accountEmailAddresses containsObject:(id)email])
                        me = record;

                    CFRelease(email);
                }
                if (me)
                    break;
            }
            CFRelease(emails);
        }
        if (me)
            break;
    }

    return me;
}
reflog
  • 7,368
  • 1
  • 39
  • 46