Search code examples
iosios6ios6.1

How do I set an Instant Message property on an Address Book contact?


I have the following code that I'm trying to use to set the AIM and Skype properties of a new contact I'm adding to Address Book:

ABRecordRef record = ABPersonCreate();
CFErrorRef an_error = NULL;

ABMutableMultiValueRef multi_aim = ABMultiValueCreateMutable(kABMultiStringPropertyType);
ABMultiValueAddValueAndLabel(multi_aim, @"ExampleNick", kABPersonInstantMessageServiceAIM, NULL);
ABRecordSetValue(record, kABPersonInstantMessageProperty, multi_aim, &an_error);

ABMutableMultiValueRef multi_skype = ABMultiValueCreateMutable(kABMultiStringPropertyType);
ABMultiValueAddValueAndLabel(multi_skype, @"example.nick", kABPersonInstantMessageServiceSkype, NULL);
ABRecordSetValue(record, kABPersonInstantMessageProperty, multi_skype, &an_error);

if (an_error != NULL) {
    NSLog(@"Error while creating person");
}

CFErrorRef error = NULL;
ABAddressBookRef address_book = ABAddressBookCreateWithOptions(NULL, &error);
ABAddressBookRequestAccessWithCompletion(address_book, ^(bool granted, CFErrorRef error) {
    if (!granted) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                        message:@"Unable to access address book"
                                                       delegate:self
                                              cancelButtonTitle:nil
                                              otherButtonTitles:nil];
        [alert show];
    } else {
        BOOL is_added = ABAddressBookAddRecord(address_book, record, &error);

        if (is_added) {
            NSLog(@"Address book entry added");
        } else {
            NSLog(@"ERROR adding address book entry: %@", error);
        }

        error = NULL;

        BOOL is_saved = ABAddressBookSave(address_book, &error);

        if (is_saved) {
            NSLog(@"Saved address book");
        } else {
            NSLog(@"ERROR saving address book: %@", error);
        }
    }

    CFRelease(record);
    CFRelease(multi_aim);
    CFRelease(multi_skype);
    CFRelease(address_book);
});

(I'm also adding first and last names but left that out of the example for brevity sake)

When the record gets added everything but the AIM and Skype fields get populated. What am I doing wrong?


Solution

  • Instants are multivalue properties of type kABMultiDictionaryPropertyType. Snippet inserting one skype id into ABRecordRef goes below. You can insert several instants into one ABRecordRef.

        ABRecordRef record = ABPersonCreate();
        NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
            (NSString*)kABPersonInstantMessageServiceSkype, (NSString*)kABPersonInstantMessageServiceKey,
            @"YourSkypeIDGoesHere", (NSString*)kABPersonInstantMessageUsernameKey, 
            nil
        ];
        CFStringRef label = NULL; // in this case 'IM' will be set. But you could use something like = CFSTR("Personal IM");
        CFErrorRef error = NULL;
        ABMutableMultiValueRef values =  ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);
        BOOL didAdd = ABMultiValueAddValueAndLabel(values, (__bridge CFTypeRef)(dictionary), label, NULL);
        BOOL didSet = ABRecordSetValue(record, kABPersonInstantMessageProperty, values, &error);
        if (!didAdd || !didSet) {
            CFStringRef errorDescription = CFErrorCopyDescription(error);
            NSLog(@"%s error %@ while inserting multi dictionary property %@ into ABRecordRef", __FUNCTION__, dictionary, errorDescription);
            CFRelease(errorDescription);
        }
        CFRelease(values);