Question

The AddressBook Framework offers a great method for initializing an ABPerson with a vCard, by using the initWithVCardRepresentation: method.

What I want to do is update a contact with a certain vCard. I can't use initWithVCardRepresentation: because this will give me a new ABPerson object with a new uniqueId and I want to keep the uniqueId in between these changes.

What's an easy way to go about doing something like this?

Thanks!

Was it helpful?

Solution

initWithVCardRepresentation is still the slickest way to turn your vCard into an ABPerson.

Just use the results of it to find the matching person in your Address Book and then iterate over the vCard properties, placing them into the existing record. The save at the end will harden your changes.

The following example assumes that the unique "keys" will be last-name, first-name. You can modify the search element if you want to include companies where no name is listed or whatever, or you could change the iteration scheme by getting [AddressBook people], and then iterating over the people and using only those records where the key-value pairs match to your satisfaction.

- (void)initOrUpdateVCardData:(NSData*)newVCardData {
    ABPerson* newVCard = [[ABPerson alloc] initWithVCardRepresentation:newVCardData];
    ABSearchEleemnt* lastNameSearchElement
      = [ABPerson searchElementForProperty:kABLastNameProperty
                                     label:nil
                                       key:nil
                                     value:[newVCard valueForProperty:kABLastNameProperty]
                                comparison:kABEqualCaseInsensitive];
    ABSearchEleemnt* firstNameSearchElement
      = [ABPerson searchElementForProperty:kABFirstNameProperty
                                     label:nil
                                       key:nil
                                     value:[newVCard valueForProperty:kABFirstNameProperty]
                                comparison:kABEqualCaseInsensitive];
    NSArray* searchElements
      = [NSArray arrayWithObjects:lastNameSearchElement, firstNameSearchElement, nil];
    ABSearchElement* searchCriteria
      = [ABSearchElement searchElementForConjunction:kABSearchAnd children:searchElements];
    AddressBook* myAddressBook = [AddressBook sharedAddressBook];
    NSArray* matchingPersons = [myAddressBook recordsMatchingSearchElement:searchCriteria];
    if (matchingPersons.count == 0)
    {
        [myAddressBook addRecord:newVCard];
    }
    else if (matchingPersons.count > 1)
    {
        // decide how to handle error yourself here: return, or resolve conflict, or whatever
    }
    else
    {
        ABRecord* existingPerson = matchingPersons.lastObject;
        for (NSString* property in [ABPerson properties])   // i.e. *all* potential properties
        {
            // if the property doesn't exist in the address book, value will be nil
            id value = [newVCard valueForProperty:property];
            if (value)
            {
                NSError* error;
                if (![existingPerson setValue:value forProperty:property error:&error] || error)
                    // handle error
            }
        }
        // newVCard with it's new unique-id will now be thrown away
    }
    [myAddressBook save];
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top