How to save image to iphone's AddressBook using SDK API? - iphone

My purpose is to process one image from image library, and save this image directly to one person record (i,e, "Tom" ), which is selected from AddressBook, I can see the new image replace Tom's previous image, but I can not save it to AddressBook.
I implemented delegate ABPeoplePickerNavigationControllerDelegate, and using following logics, but whatever I tried, modified records can not be saved to address books.
Any clues or suggest ? Thanks
ABAddressBookRef addressBook= ABAddressBookCreate();
CFErrorRef error = NULL;
BOOL wantToSaveChanges = YES;
ABRecordSetValue(person, kABPersonFirstNameProperty, #"Shi", &error);//, &error)
NSData * dataRef = UIImagePNGRepresentation(cellImage);
ABPersonSetImageData(person, dataRef, &error);
if (ABAddressBookHasUnsavedChanges(addressBook)) {\
NSLog(#"need to save ");
if (wantToSaveChanges) {
ABAddressBookSave(addressBook, &error);
} else {
ABAddressBookRevert(addressBook);
}
}else {
NSLog(#"no changes");
}
if (error != NULL) {/*... Handle error. ...*/
NSLog(#"error happened here " );
}
CFRelease(addressBook);

See:
Setting Address Book image for a contact doesn't seem to work
and
ABPersonSetImageData Only Altering the Contact Thumbnail and Not the Full Pic

Related

Read/Parse Data from vCard

Is there any framework/library available in iOS SDK to read/parse data in vCard format?
I am receiving data in a vcard format in a NSString and I have to parse it.
Googled a lot, but couldn't find solution yet.
BEGIN:VCARD
VERSION:2.1
N:LastName;FirstName;MiddleName;Prefix;Sufix
ADR;TYPE=HOME: postbox;street2;street1;city;state;zip;country
BDAY:2010-08-19
END:VCARD
I did found some solutions for you...
Have a look at the following links...
1) Want ready made sample code==>Click here
2) Writing to Vcard==>Click here
Code Relevent to you:
ABAddressBookRef addressBook = ABAddressBookCreate(); // create address book record
ABRecordRef person = ABPersonCreate(); // create a person
NSString *phone = #"0123456789"; // the phone number to add
//Phone number is a list of phone number, so create a multivalue
ABMutableMultiValueRef phoneNumberMultiValue = ABMultiValueCreateMutable(kABPersonPhoneProperty);
ABMultiValueAddValueAndLabel(phoneNumberMultiValue ,phone,kABPersonPhoneMobileLabel, NULL);
ABRecordSetValue(person, kABPersonFirstNameProperty, #"FirstName" , nil); // first name of the new person
ABRecordSetValue(person, kABPersonLastNameProperty, #"LastName", nil); // his last name
ABRecordSetValue(person, kABPersonPhoneProperty, phoneNumberMultiValue, &anError); // set the phone number property
ABAddressBookAddRecord(addressBook, person, nil); //add the new person to the record
ABRecordRef group = ABGroupCreate(); //create a group
ABRecordSetValue(group, kABGroupNameProperty,#"My Group", &error); // set group's name
ABGroupAddMember(group, person, &error); // add the person to the group
ABAddressBookAddRecord(addressBook, group, &error); // add the group
ABAddressBookSave(addressBook, nil); //save the record
CFRelease(person); // relase the ABRecordRef variable
3) Importing vCard sample code==>Click here
4) For creating custom parser ==> Click here
OS X v10.11 and iOS 9 introduces CNContactVCardSerialization which makes parsing a VCard a breeze.

app crash when accessing First name from address book due to memory management

I am trying to access all the first name value field from the address book. I am using this code for this
CFStringRef firstName = ABRecordCopyValue(aSource, kABPersonFirstNameProperty);
first_name=[NSString stringWithFormat:#"%#",firstName];
CFRealease(firstname)
I am not using ARC. So i need to CFRealease(firstname) at the end. But in my code when i add CFRealease(firstname) my app crashes at this point and without this the app works fine.
But when i try to analyse my app by using analyzer it says object Leaked: object allocated and stored into 'firstname' is not refrenced later in the execution path and has a retain count of +1.
Case is same for midname and last name whose code are given below.
CFStringRef midname = ABRecordCopyValue(aSource, kABPersonMiddleNameProperty);
mid_name=[NSString stringWithFormat:#"%#",midname];
CFRelease(midname);
CFStringRef lastName = ABRecordCopyValue(aSource, kABPersonLastNameProperty);
last_name=[NSString stringWithFormat:#"%#",lastName];
CFRelease(lastName);
Please tell where i am doing it wrong. Thanks in advance.
Assuming that you store a reference to the first name in firstname (not firstName), your app will crash when you try to release the object referenced if firstname is nil. This can happen if your app doesn't have access to the address book (the contacts data base), because the user has not yet granted access to it. This must be done stating with iOS 6. In this case, no contacts are returned.
You could ask for access e.g. using the following code:
-(bool)userGrantedReadAccessToContacts
{
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // iOS 6
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(contactsRef, ^(bool granted, CFErrorRef error) {
accessGranted = granted;
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
else { // iOS 5 or earlier
accessGranted = YES;
}
return accessGranted;
}

iPhone: Adding contact to a group not working on device but working on simulator in ABAddressbook

Adding contact to a group not working on device but working on simulator in ABAddressbook
Gives no error but contact is not reflected in particular group in contacts
but works fine on Simulator
I am Using this code
if (person) {
ABAddressBookAddRecord(addressBook, person, nil);
ABAddressBookSave(addressBook, &error);
BOOL isADDED = ABGroupAddMember(groupNameRef, person, &error);
NSError *error1 = (__bridge_transfer NSError *)error;
NSLog(#"Reason = %#", error1.localizedFailureReason);
BOOL iSSaved = ABAddressBookSave(addressBook, &error);
}
works fine on Simulator but not on device
It will help you to start by using error-checking correctly. Here is the structure of an error-checked routine:
if (person) {
bool ok;
CFErrorRef err = nil;
ok = ABAddressBookAddRecord(addressBook, person, &err);
if (!ok) {
NSLog(#"%#", err);
return;
}
ok = ABAddressBookSave(addressBook, &err);
if (!ok) {
NSLog(#"%#", err);
return;
}
ok = ABGroupAddMember(groupNameRef, person, &err);
if (!ok) {
NSLog(#"%#", err);
return;
}
ok = ABAddressBookSave(addressBook, &err);
if (!ok) {
NSLog(#"%#", err);
return;
}
}
Notice the pattern here. The function returns a bool. You examine that bool. If it is false, then you examine the error returned by indirection. If you follow this pattern correctly, you will get better information about what is going wrong.
Edit: Make sure you actually have access to the contacts database. I'm assuming you do, but a major difference between the Simulator and the device is that the Simulator grants access automatically, whereas on the device the user must be presented with the access request dialog (call ABAddressBookRequestAccessWithCompletion) or else there won't be access and attempts to work with the contacts database will fail, perhaps silently.

Custom addressbook for ABPeoplePickerNavigationController on iPhone

I am trying to create a custom addressbook on the iPhone by adding new records to the device address book (basically, merging a private contact list with the device AB). I then want to let the user select a contact, which I thought I could do with the .addressbook property of ABPeoplePickerNavigationController:
ABAddressBookRef contacts = ABAddressBookCreate();
for (PrivateUserType *user in rosterItems)
{
CFErrorRef err = NULL;
ABRecordRef ref = ABPersonCreate();
ABRecordSetValue(ref, kABPersonLastNameProperty, (CFStringRef)user.lastName, &err);
if (err != NULL)
{
NSString *errorStr = [(NSString *)CFErrorCopyDescription(err) autorelease];
NSLog(#"Can not set name: %#", errorStr);
}
...
ABAddressBookAddRecord(contacts, ref, &err);
if (err != NULL)
{
NSString *errorStr = [(NSString *)CFErrorCopyDescription(err) autorelease];
NSLog(#"Error adding XMPP roster user to addressbook: %#", errorStr);
}
}
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.addressBook = contacts;
[viewController presentModalViewController:picker animated:YES];
[picker release];
The entries are successfully added to the addressbook (which I can verify if I do an ABAddressBookSave() after the loop to add everything in). However, the entries are not shown by picker (unless I save contacts, which of course saves all changes into the device addressbook).
Is there a way to do this? This is on iOS 4.3.1.
Thanks!
As Toro said, you need save any changes to database first. ABPeoplePickerNavigationController not intended to work with uncommit data or with custom data.
You can see rather fresh topic on Apple Dev Forums
https://devforums.apple.com/message/370070#370070
where similar question was asked. And guy from Apple says that "I can't see any way to do this." But he suggest filling a bug for this to implement this feature in future release of iOS.
All you can do now is code your own UI for this AddressBook from the ground :(
updated: he-he. I found your question on App Dev Forum too )))
You need to save any changes to database by ABAddressBookSave() method.
The apple doc link.

how to create groups in contacts in iPhone apps?

I am developing an iPhone application which handles groups in iPhone contacts, but as my observation there is no facility to create groups in iPhone contacts, but in the SDK we have been given a framework for creating and managing groups, so I decided to create groups from application interface and add contacts to that created groups.
Can anyone help how to create groups in iPhone contacts or is my approach correct to create groups from app?
If you have found the solution, suggest to close this question. If not, the following code is for your reference:
- (void)addNewGroup:(NSString *)groupName
{
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef newGroup = ABGroupCreate();
// Save groupName into ABRecord
CFErrorRef error = NULL;
BOOL result = ABRecordSetValue(newGroup, kABGroupNameProperty, (CFTypeRef)groupName, &error);
if (!result)
{
NSLog(#"Failed to create new group reference with error, %#", error);
CFRelease(addressBook);
return;
}
result = ABAddressBookAddRecord(addressBook, newGroup, &error);
if (!result)
{
NSLog(#"Failed to save new group record to address book with error, %#", error);
CFRelease(addressBook);
return;
}
result = ABAddressBookSave(addressBook,&error);
if (!result)
{
NSLog(#"Failed to save change back to address book with error, %#", error);
}
CFRelease(addressBook);
}