How to edit a contact? - iphone

Is there any way to edit a contact programmatically in the iPhone? For example, I want to modify a contact which is returned by ABPeoplePickerNavigationController. How can I do this? I have:
(BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
NSString *phoneNum = #"01234567890";
ABAddressBookRef addressBook = ABAddressBookCreate();
contact = ABAddressBookGetPersonWithRecordID(addressBook, ABRecordGetRecordID(person));
if(phoneNum && contact != NULL)
{
ABMutableMultiValueRef phoneNumberMultiValue = ABMultiValueCreateMutable(kABMultiStringPropertyType);
ABMultiValueAddValueAndLabel(phoneNumberMultiValue, phoneNum, kABPersonPhoneMobileLabel, NULL);
[self dismissModalViewControllerAnimated:YES];
ABRecordSetValue(contact, kABPersonPhoneProperty, phoneNumberMultiValue, nil);
//THIS CODE IS NOT BEHAVING AS I EXPECTED,
//if(ABAddressBookHasUnsavedChanges(addressBook))//Anyway this needs to be checked
{
ABAddressBookSave(addressBook, NULL);
}
}
return NO;
}
The call to ABAddressBookSave(addressBook, NULL); is working. But the problem is, all the old information of the "contact" is removed from the address book and only the "phoneNum" is saved at the end.
How can I solve this problem?

Apologies for the previous answer - I read the question wrong...! I thought that the contact wasn't saving at all on the address book.
It seems that the only information lost is the contact's other phone numbers, correct? Meaning that the ABRecordRef's other details, such as address, notes, birthdates, etc. remain intact.
If this is correct, I assume that the only feasible way to counter this deletion of other phone numbers is to simply append a PhoneLabel to the contact's existing kABPersonPhoneProperty. Instead of creating a new ABMutableMultiValueRef for the phone numbers, copy it from the record like so:
ABMutableMultiValueRef phoneNumberMultiValue = ABMultiValueCreateMutableCopy((ABMultiValueRef)ABRecordCopyValue(contact, kABPersonPhoneProperty));
With this, you can now append the new phone number with the same code:
ABMultiValueAddValueAndLabel(phoneNumberMultiValue, phoneNum, kABPersonPhoneMobileLabel, NULL);
What's neat about this is that no replacing or deletion occurs - the app simply adds another phone number to the contact's phone numbers property. :D
Hope this helps.

The first thing you should do is pass in a reference to a CFErrorRef as the second argument to ABAddressBookSave; it may be that it's trying to report an error, but unable to, since you don't give it this argument.

Currently there is no way to EDIT and SAVE the contact to the address book. The IPhone API does not support this requirement. In order to EDIT a specific contact we need to get a reference of that contact by record ID and copy all the information to the reference and then save that contact to the address book.

Related

how to add a note to iphone contact?

I am developing an App that stores contacts in the address book . I would like to add notes field in my implementation , I know that to add a phone number this is the code to be used :
ABMultiValueRef multiPhone = ABMultiValueCreateMutable(kABMultiRealPropertyType);
ABMultiValueAddValueAndLabel(multiPhone, (__bridge_retained CFStringRef)Tel, kABWorkLabel, NULL);
ABMultiValueAddValueAndLabel(multiPhone, (__bridge_retained CFStringRef)Fax, kABPersonPhoneWorkFAXLabel, NULL);
ABRecordSetValue(contact, kABPersonPhoneProperty, multiPhone, nil);
CFRelease(multiPhone);
I know that the equivalent of kABPersonPhoneProperty is kABNoteProperty but what is the equivalent of kABWorkLabel for the note field?
Thanks
The note property, identified by kABNoteProperty, is a single-value property, not a multi-value property, so there's no corresponding label. The phone property is multi-value: it can contain several different values at the same time, so you need labels to distinguish the values. The note property is like the first name or last name property -- these can only have one value at a time. Use ABRecordSetValue() for this:
bool ABRecordSetValue (
ABRecordRef record,
ABPropertyID property,
CFTypeRef value,
CFErrorRef *error
);
There is no equivalent of kABWorkLabel for kABNoteProperty, because the note property is a single string, not a multivalue.
CFErrorRef error;
if (!ABRecordSetValue(contact, kABNoteProperty, (__bridge CFStringRef)#"hello world", &error)) {
// handle error
}

How to modify a contact number in address book programmatically?

I am currently writing an app which should enable the user to modify the contact details (mainly numbers) in the app, and then these modifications should be reflected directly to the Address Book.
I searched thoroughly on the internet, but all the examples I found were either to load the contacts or add new contact, but nothing on modifying an existing contact.
also how can I get a list of all phone numbers of a single contact, in case he has several numbers stored.
To allow a user to edit their details directly, see Apple's documentation on displaying and editing a person record. The initial section of that says, "Set the delegate, which must adopt the ABPersonViewControllerDelegate protocol. To allow the user to edit the record, set allowsEditing to YES."
For example:
ABPersonViewController *personViewController = [[ABPersonViewController alloc] init];
personViewController.personViewDelegate = self;
personViewController.allowsEditing = YES;
Other than setting allowsEditing, the code would be exactly the same as that required to display a person's details without editing. (This code was drawn from this answer which displays a fuller example regarding deleting a contact from the address book.)
However, I see your title refers to doing so programatically. Apple's Address Book Programing Guide for iOS says, "Remember that the Address Book database is ultimately owned by the user, so applications must be careful not to make unexpected changes to it. Generally, changes should be initiated or confirmed by the user."
However, it is possible. The following example appears on p.17 of that document:
ABRecordRef aRecord = ABPersonCreate();
CFErrorRef anError = NULL;
bool didSet;
didSet = ABRecordSetValue(aRecord, kABPersonFirstNameProperty, CFSTR("Katie"), &anError);
if (!didSet) {/* Handle error here. */}
didSet = ABRecordSetValue(aRecord, kABPersonLastNameProperty, CFSTR("Bell"), &anError);
if (!didSet) {/* Handle error here. */}
CFStringRef firstName, lastName;
firstName = ABRecordCopyValue(aRecord, kABPersonFirstNameProperty);
lastName = ABRecordCopyValue(aRecord, kABPersonLastNameProperty);
/* ... Do something with firstName and lastName. ... */
CFRelease(aRecord);
CFRelease(firstName);
CFRelease(lastName);

iPhone: How do you get the names of all the address books on the iPhone?

Some users have multiple address books in their iPhone Contacts, as a result of different synchronization connections they have made with e.g. Exchange Servers.
How is it possible to get all of these different address books? I would be interested in getting the names under which these different address books are saved and accessing their contact information.
Thank you!
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef sourcesArray = ABAddressBookCopyArrayOfAllSources(addressBook);
for (CFIndex i = 0; i < CFArrayGetCount(sourcesArray); i++) {
ABRecordRef source = (ABRecordRef)CFArrayGetValueAtIndex(sourcesArray, i);
ABRecordID sourceID = ABRecordGetRecordID(source);
CFNumberRef sourceType = (CFNumberRef)ABRecordCopyValue(source, kABSourceTypeProperty);
CFStringRef sourceName = (CFStringRef)ABRecordCopyValue(source, kABSourceNameProperty);
NSLog(#"source id=%d type=%d name=%#", sourceID, [(NSNumber *)sourceType intValue], sourceName);
CFRelease(sourceType);
if (sourceName != NULL) CFRelease(sourceName); // some source names are NULL
}
CFRelease(sourcesArray);
CFRelease(addressBook);
Note that, as of iOS 4, not all sources return a name. You may provide your own names based on type.
Use ABAddressBookCopyArrayOfAllPeopleInSource(addressBook, source) to get entries in a source.
There is only a single, centralized address book database on iOS accessible by a set of C functions, see ABAddressBook and the iOS address book programming guide.
You may be referring to groups within that address book. In that case, you can get the list of groups using the ABAddressBookCopyArrayOfAllGroups function as described in the reference on ABGroup.

fetching all phone numbers from address book

I want fetch all phone numbers from address book and i want to store in one array.
For that am writing this code,but am getting this error at second line Program received signal: “EXC_BAD_ACCESS”
ABRecordRef person;
ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSArray* phoneNumbers = (NSArray*)ABMultiValueCopyArrayOfAllValues(phoneNumberProperty);
// CFRelease(phoneNUmberProperty);
NSLog(#"Phone numbers = %#", phoneNumbers);
[phoneNumbers release];
please help me what are changes can i do.
Thanks in advance
ABRecordCopyValue will not get you all the phone numbers of a address book. You can use this to look up a property of 1 person. Use ABAddressBookCopyArrayOfAllPeople to get all the persons from the address book first.

Odd error when retrieving phone numbers from iPhone Address Book using API

When I try to retrieve phone numbers from Address Book contacts, the result is always nil if the contact has an e-mail address. This is obviously a big problem...such a big one, in fact, that I have a hard time believing I'm not doing something wrong. But every test I've done--including using other, unrelated code samples--gives the same result.
I've used the code below to successfully retrieve email addresses:
+ (NSArray*)emailFromRecordRef:(ABRecordRef)personRef
{
ABMultiValueRef emailAddressesRef = ABRecordCopyValue(personRef, kABPersonEmailProperty);
NSArray* emailAddresses = nil;
if (emailAddressesRef != nil)
{
emailAddresses = [(NSArray*)ABMultiValueCopyArrayOfAllValues(emailAddressesRef) autorelease];
CFRelease(emailAddressesRef);
}
return emailAddresses;
}
...but when I adapt the same code to retrieve phone numbers:
+ (NSArray*)phoneNumbersFromRecordRef:(ABRecordRef)personRef
{
ABMultiValueRef phoneNumbersRef = ABRecordCopyValue(personRef, kABPersonPhoneProperty);
NSArray* phoneNumbers = nil;
if (phoneNumbersRef != nil)
{
phoneNumbers = [(NSArray*)ABMultiValueCopyArrayOfAllValues(phoneNumbersRef) autorelease];
CFRelease(phoneNumbersRef);
}
return phoneNumbers;
}
...it only retrieves phone numbers for users that don't have email addresses. If they have email addresses, no phone numbers are returned.
Has anyone out there successfully retrieved phone numbers from Address Book contacts?
Thanks.
Turns out, of course, I was doing something wrong. Apparently you need to keep the reference to AddressBook alive (retained) during the entire time you're requesting additional attributes like phone numbers. When I kept it alive, the phone number issue went away.