Heyo!
Is there a way how when a user taps a button it can add or update a contact into the actual Apple Contacts Book? Some festivals have email responses include a "name card" that the receiver can download and find in their contact book.
If doing this in iOS 9 or later, you should use the Contacts framework:
#import Contacts;
You also need to update your Info.plist, adding a NSContactsUsageDescription to explain why your app requires access to contacts.
Then, when you then want to programmatically add the contact, then you can do something like:
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if (status == CNAuthorizationStatusDenied || status == CNAuthorizationStatusRestricted) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:#"Access to contacts." message:#"This app requires access to contacts because ..." preferredStyle:UIAlertControllerStyleActionSheet];
[alert addAction:[UIAlertAction actionWithTitle:#"Go to Settings" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:#{} completionHandler:nil];
}]];
[alert addAction:[UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:alert animated:TRUE completion:nil];
return;
}
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!granted) {
dispatch_async(dispatch_get_main_queue(), ^{
// user didn't grant access;
// so, again, tell user here why app needs permissions in order to do it's job;
// this is dispatched to the main queue because this request could be running on background thread
});
return;
}
// create contact
CNMutableContact *contact = [[CNMutableContact alloc] init];
contact.familyName = #"Doe";
contact.givenName = #"John";
CNLabeledValue *homePhone = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:[CNPhoneNumber phoneNumberWithStringValue:#"312-555-1212"]];
contact.phoneNumbers = #[homePhone];
CNSaveRequest *request = [[CNSaveRequest alloc] init];
[request addContact:contact toContainerWithIdentifier:nil];
// save it
NSError *saveError;
if (![store executeSaveRequest:request error:&saveError]) {
NSLog(#"error = %#", saveError);
}
}];
Or, even better, if you want to add the contact using the ContactUI framework (giving the user visual confirmation of the contact and let them tailor it as they see fit), you can import both frameworks:
#import Contacts;
#import ContactsUI;
And then:
CNContactStore *store = [[CNContactStore alloc] init];
// create contact
CNMutableContact *contact = [[CNMutableContact alloc] init];
contact.familyName = #"Smith";
contact.givenName = #"Jane";
CNLabeledValue *homePhone = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:[CNPhoneNumber phoneNumberWithStringValue:#"301-555-1212"]];
contact.phoneNumbers = #[homePhone];
CNContactViewController *controller = [CNContactViewController viewControllerForUnknownContact:contact];
controller.contactStore = store;
controller.delegate = self;
[self.navigationController pushViewController:controller animated:TRUE];
My original answer, using the AddressBook and AddressBookUI frameworks for iOS versions before 9, is below. But if only supporting iOS 9 and later, use the Contacts and ContactsUI frameworks as outlined above.
--
If you want to add a contact to the user's address book, you use AddressBook.Framework to create a contact, and then you use the AddressBookUI.Framework to present the user interface to allow the user to add it to their personal address book using ABUnknownPersonViewController. Thus, you can:
Add AddressBook.Framework and AddressBookUI.Framework to your list under Link Binary With Libraries;
Import the .h files:
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
Write the code to create a contact, e.g.:
// create person record
ABRecordRef person = ABPersonCreate();
// set name and other string values
ABRecordSetValue(person, kABPersonOrganizationProperty, (__bridge CFStringRef) venueName, NULL);
if (venueUrl) {
ABMutableMultiValueRef urlMultiValue = ABMultiValueCreateMutable(kABMultiStringPropertyType);
ABMultiValueAddValueAndLabel(urlMultiValue, (__bridge CFStringRef) venueUrl, kABPersonHomePageLabel, NULL);
ABRecordSetValue(person, kABPersonURLProperty, urlMultiValue, nil);
CFRelease(urlMultiValue);
}
if (venueEmail) {
ABMutableMultiValueRef emailMultiValue = ABMultiValueCreateMutable(kABMultiStringPropertyType);
ABMultiValueAddValueAndLabel(emailMultiValue, (__bridge CFStringRef) venueEmail, kABWorkLabel, NULL);
ABRecordSetValue(person, kABPersonEmailProperty, emailMultiValue, nil);
CFRelease(emailMultiValue);
}
if (venuePhone) {
ABMutableMultiValueRef phoneNumberMultiValue = ABMultiValueCreateMutable(kABMultiStringPropertyType);
NSArray *venuePhoneNumbers = [venuePhone componentsSeparatedByString:#" or "];
for (NSString *venuePhoneNumberString in venuePhoneNumbers)
ABMultiValueAddValueAndLabel(phoneNumberMultiValue, (__bridge CFStringRef) venuePhoneNumberString, kABPersonPhoneMainLabel, NULL);
ABRecordSetValue(person, kABPersonPhoneProperty, phoneNumberMultiValue, nil);
CFRelease(phoneNumberMultiValue);
}
// add address
ABMutableMultiValueRef multiAddress = ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);
NSMutableDictionary *addressDictionary = [[NSMutableDictionary alloc] init];
if (venueAddress1) {
if (venueAddress2)
addressDictionary[(NSString *) kABPersonAddressStreetKey] = [NSString stringWithFormat:#"%#\n%#", venueAddress1, venueAddress2];
else
addressDictionary[(NSString *) kABPersonAddressStreetKey] = venueAddress1;
}
if (venueCity)
addressDictionary[(NSString *)kABPersonAddressCityKey] = venueCity;
if (venueState)
addressDictionary[(NSString *)kABPersonAddressStateKey] = venueState;
if (venueZip)
addressDictionary[(NSString *)kABPersonAddressZIPKey] = venueZip;
if (venueCountry)
addressDictionary[(NSString *)kABPersonAddressCountryKey] = venueCountry;
ABMultiValueAddValueAndLabel(multiAddress, (__bridge CFDictionaryRef) addressDictionary, kABWorkLabel, NULL);
ABRecordSetValue(person, kABPersonAddressProperty, multiAddress, NULL);
CFRelease(multiAddress);
// let's show view controller
ABUnknownPersonViewController *controller = [[ABUnknownPersonViewController alloc] init];
controller.displayedPerson = person;
controller.allowsAddingToAddressBook = YES;
// current view must have a navigation controller
[self.navigationController pushViewController:controller animated:YES];
CFRelease(person);
See the ABUnknownPersonViewController Class Reference or the Prompting the User to Create a New Person Record from Existing Data section of the Address Book Programming Guide.
To present default contact controller
Step 1:
Add ContactUi.framework into project and import
#import <Contacts/Contacts.h>
#import <ContactsUI/ContactsUI.h>
Step2:
Add this code
-(void)showAddContactController{
//Pass nil to show default contact adding screen
CNContactViewController *addContactVC = [CNContactViewController viewControllerForNewContact:nil];
addContactVC.delegate=self;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addContactVC];
[viewController presentViewController:navController animated:NO completion:nil];
}
Step3:
For getting call back when pressing DONE or CANCEL, Add <CNContactViewControllerDelegate>and implement the delegate method.
- (void)contactViewController:(CNContactViewController *)viewController didCompleteWithContact:(nullable CNContact *)contact{
//You will get the callback here
}
#import Contacts;
-(void)addToContactList
{
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if (status == CNAuthorizationStatusDenied || status == CNAuthorizationStatusRestricted) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:#"This app previously was refused permissions to contacts; Please go to settings and grant permission to this app so it can add the desired contact" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alert animated:TRUE completion:nil];
return;
}
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!granted) {
dispatch_async(dispatch_get_main_queue(), ^{
// user didn't grant access;
// so, again, tell user here why app needs permissions in order to do it's job;
// this is dispatched to the main queue because this request could be running on background thread
});
return;
}
// create contact
CNMutableContact *contact = [[CNMutableContact alloc] init];
contact.givenName = #"Test";
contact.familyName = #"User";
CNLabeledValue *homePhone = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:[CNPhoneNumber phoneNumberWithStringValue:#"91012-555-1212"]];
contact.phoneNumbers = #[homePhone];
CNSaveRequest *request = [[CNSaveRequest alloc] init];
[request addContact:contact toContainerWithIdentifier:nil];
// save it
NSError *saveError;
if (![store executeSaveRequest:request error:&saveError]) {
NSLog(#"error = %#", saveError);
}
}];
}
Related
Can you please help me with this error that I'am getting...
Basically, I'm trying to import all my contact list from my address book. Also I'm checking the phone number label, but the error that I'm getting is "Use of undeclared identifier PhonesViewController ios7 xCode" and I have that viewController, and also I have added the class in storyboard for the viewcontroller although I think that it is not necessary
Thanks in advance
Here is my code:
#import "PhonesViewController.h"
#implementation PhonesViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
- (BOOL)PhohesViewController: (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:#"mobile"])// Mobile number saving.
{
[mobile appendFormat:#"%#", phoneNumber];
}
else if ([phoneLabel isEqualToString:#"work"])// 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:#"mobile"])// Home mail.
{
[generalMail appendFormat:#"%#", mail];
}
else if ([mailLabel isEqualToString:#"work"])// 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;
}
}
#end
Looks like a typo to me.
// Phohes?
- (BOOL)PhohesViewController: (ABPeoplePickerNavigationController *)picker //Phohes? shouldContinueAfterSelectingPerson:(ABRecordRef)person
Looking at your code and the image you've posted, you're defining a method within a method, you can't do that.
I have used Anypic open source to save a photo taken with the app to an in-app feed. I would like to convert it to save videos instead of photos. How would I go about doing this. Here is the code that i am using to save the photo-
- (BOOL)shouldUploadImage:(UIImage *)anImage {
// Resize the image to be square (what is shown in the preview)
UIImage *resizedImage = [anImage resizedImageWithContentMode:UIViewContentModeScaleAspectFit
bounds:CGSizeMake(560.0f, 560.0f)
interpolationQuality:kCGInterpolationHigh];
// Create a thumbnail and add a corner radius for use in table views
UIImage *thumbnailImage = [anImage thumbnailImage:86.0f
transparentBorder:0.0f
cornerRadius:10.0f
interpolationQuality:kCGInterpolationDefault];
// Get an NSData representation of our images. We use JPEG for the larger image
// for better compression and PNG for the thumbnail to keep the corner radius transparency
NSData *imageData = UIImageJPEGRepresentation(resizedImage, 0.8f);
NSData *thumbnailImageData = UIImageJPEGRepresentation(thumbnailImage, 0.8f);
if (!imageData || !thumbnailImageData) {
return NO;
}
// Create the PFFiles and store them in properties since we'll need them later
self.photoFile = [PFFile fileWithData:imageData];
self.thumbnailFile = [PFFile fileWithData:thumbnailImageData];
// Save the files
[self.photoFile saveInBackground];
[self.thumbnailFile saveInBackground];
}
- (void)doneButtonAction:(id)sender {
NSDictionary *userInfo = [NSDictionary dictionary];
NSString *trimmedComment = [self.commentTextField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if (trimmedComment.length != 0) {
userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
trimmedComment,kPAPEditPhotoViewControllerUserInfoCommentKey,
nil];
}
if (!self.photoFile || !self.thumbnailFile) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Couldn't post your photo" message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:#"Dismiss", nil];
[alert show];
return;
}
// both files have finished uploading
// create a photo object
PFObject *photo = [PFObject objectWithClassName:kPAPPhotoClassKey];
[photo setObject:[PFUser currentUser] forKey:kPAPPhotoUserKey];
[photo setObject:self.photoFile forKey:kPAPPhotoPictureKey];
[photo setObject:self.thumbnailFile forKey:kPAPPhotoThumbnailKey];
// photos are public, but may only be modified by the user who uploaded them
PFACL *photoACL = [PFACL ACLWithUser:[PFUser currentUser]];
[photoACL setPublicReadAccess:YES];
photo.ACL = photoACL;
// Request a background execution task to allow us to finish uploading the photo even if the app is backgrounded
self.photoPostBackgroundTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:self.photoPostBackgroundTaskId];
}];
// save
[photo saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
NSLog(#"Photo uploaded");
[[PAPCache sharedCache] setAttributesForPhoto:photo likers:[NSArray array] commenters:[NSArray array] likedByCurrentUser:NO];
// userInfo might contain any caption which might have been posted by the uploader
if (userInfo) {
NSString *commentText = [userInfo objectForKey:kPAPEditPhotoViewControllerUserInfoCommentKey];
if (commentText && commentText.length != 0) {
// create and save photo caption
PFObject *comment = [PFObject objectWithClassName:kPAPActivityClassKey];
[comment setObject:kPAPActivityTypeComment forKey:kPAPActivityTypeKey];
[comment setObject:photo forKey:kPAPActivityPhotoKey];
[comment setObject:[PFUser currentUser] forKey:kPAPActivityFromUserKey];
[comment setObject:[PFUser currentUser] forKey:kPAPActivityToUserKey];
[comment setObject:commentText forKey:kPAPActivityContentKey];
PFACL *ACL = [PFACL ACLWithUser:[PFUser currentUser]];
[ACL setPublicReadAccess:YES];
comment.ACL = ACL;
[comment saveEventually];
[[PAPCache sharedCache] incrementCommentCountForPhoto:photo];
}
}
[[NSNotificationCenter defaultCenter] postNotificationName:PAPTabBarControllerDidFinishEditingPhotoNotification object:photo];
} else {
NSLog(#"Photo failed to save: %#", error);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Couldn't post your photo" message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:#"Dismiss", nil];
[alert show];
}
[[UIApplication sharedApplication] endBackgroundTask:self.photoPostBackgroundTaskId];
}];
[self.parentViewController dismissModalViewControllerAnimated:YES];
}
PFFile *videoFile = [PFFile fileWithData:videoData];
[self.videoFile saveInBackground];
You would treat the video as any other file in parse. I would look into Apples documentation for video on handling video files on iOS.
Currently I'm using the following code to instantiate a UIActivityViewController:
NSArray *itemsToShare = [[NSArray alloc] initWithObjects:bodyMessage, nil];
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:itemsToShare applicationActivities:nil];
activityVC.excludedActivityTypes = [[NSArray alloc] initWithObjects: UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll, UIActivityTypePostToWeibo,UIActivityTypePostToFacebook,UIActivityTypePostToTwitter, nil];
[activityVC setValue:subject forKey:#"subject"];
[self presentViewController:activityVC animated:YES completion:nil];
[activityVC setCompletionHandler:^(NSString *activityType, BOOL done)
{
NSString *ServiceType;
if ( [activityType isEqualToString:UIActivityTypeMail] ) ServiceType = #"Mail.";
if ( [activityType isEqualToString:UIActivityTypeMessage] ) ServiceType = #"Messenger.";
NSMutableString *shareWithActivityResultMessage;
NSString *alertTitle;
if (done)
{
alertTitle = #"Success!";
shareWithActivityResultMessage = [NSMutableString stringWithString:successMessage];
[shareWithActivityResultMessage appendString:ServiceType];
}
else
{
// didn't succeed.
alertTitle = #"Error";
shareWithActivityResultMessage = [NSMutableString stringWithString:errorMessage];
}
When I cancel composing, the ActivityVC done = false and thus the error message is triggered. Is there a way to detect canceling as opposed to an actual error in sending the message?
You can using the new UIActivityViewControllerCompletionWithItemsHandler type in iOS 8:
activityVC.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError){
...
}
Just check the activityError property
In my app, I am fetching the e-mail id from address box using PersonPicker view.
When i select any e-mail id, i try to open the e-mail dialog. But it will just open & close immediatly.
I can't able to solve this issue.
I got code from Here
My code is as follow:
-(BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{
// Get the first and the last name. Actually, copy their values using the person object and the appropriate
// properties into two string variables equivalently.
// Watch out the ABRecordCopyValue method below. Also, notice that we cast to NSString *.
NSString *firstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSString *lastName = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
// Compose the full name.
NSString *fullName = #"";
// Before adding the first and the last name in the fullName string make sure that these values are filled in.
if (firstName != nil) {
fullName = [fullName stringByAppendingString:firstName];
}
if (lastName != nil) {
fullName = [fullName stringByAppendingString:#" "];
fullName = [fullName stringByAppendingString:lastName];
}
// Get the multivalue e-mail property.
CFTypeRef multivalue = ABRecordCopyValue(person, property);
// Get the index of the selected e-mail. Remember that the e-mail multi-value property is being returned as an array.
CFIndex index = ABMultiValueGetIndexForIdentifier(multivalue, identifier);
// Copy the e-mail value into a string.
email = (NSString *)ABMultiValueCopyValueAtIndex(multivalue, index);
NSLog(#"%#",email);
// Create a temp array in which we'll add all the desired values.
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
[tempArray addObject:fullName];
// Save the email into the tempArray array.
[tempArray addObject:email];
// Now add the tempArray into the contactsArray.
[contactsArray addObject:tempArray];
NSLog(#"%#",contactsArray);
// Release the tempArray.
[tempArray release];
// Reload the table to display the new data.
[table reloadData];
// Dismiss the contacts view controller.
[contacts dismissModalViewControllerAnimated:YES];
[contacts release];
MFMailComposeViewController* Apicker = [[MFMailComposeViewController alloc] init];
if (Apicker != nil)
{
[Apicker setSubject:#""];
NSString * someString = nil;
someString=#"Google";
[Apicker setMessageBody:someString isHTML:YES];
NSArray *toRecipients = [NSArray arrayWithObjects:email, nil];
[Apicker setToRecipients:toRecipients];
Apicker.mailComposeDelegate = self;
[self presentModalViewController:Apicker animated:YES];
[Apicker release];
}
return NO;
}
I think it may be the issue of dismiss & present the modal view.
your problem with dismiss and present is that the two overlap. -- dismiss it and THEN show it kinda like you did BUT you run into a problem because the stuff is animated. dont animate there or delay the presetting till after the dismissal
I am working on an iPhone application which works with AddressBook contacts. I am trying to fetch the image from address book and edit then save that image.
But I don't know how to update and save that image. Please give me a solution if anybody knows about this.
Thanx in advance.
Here's the .h file
ABAddressBookRef addressBook;
IBOutlet UILabel *lblName;
IBOutlet UIImageView *imgGet;
UIImage *imgContact;
NSString* name;
The .m file
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {
name = [(NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty) autorelease];
lblName.text = name;
if(ABPersonHasImageData(person)) {
CFDataRef imageData = ABPersonCopyImageData(person);
imgContact = [UIImage imageWithData:(NSData *)imageData];
imgGet.image = imgContact;
CFRelease(imageData);
} else {
imgGet.image = [UIImage imageNamed:#"ABPicturePerson#2x.png"];
}
[self.navigationController dismissViewControllerAnimated:(YES) completion:nil];
return NO;
}
Here After fetching image and name from above method then i open gallery and select an image then click on below method button but image not saved or update in address book
-(IBAction)btnSaveClicked {
ABRecordRef person = ABPersonCreate();
NSData *dataRef = UIImagePNGRepresentation(imgGet.image);
CFDataRef cfdata = CFDataCreate(NULL, [dataRef bytes], [dataRef length]);
ABPersonSetImageData(person, (CFDataRef)dataRef, nil);
CFErrorRef error;
ABPersonRemoveImageData(person, &error); // <-- clean any image first from ref
//ABAddressBookSave(addressBook, &error);
ABPersonSetImageData(person, cfdata, &error);
ABAddressBookSave(addressBook, &error);
CFRelease(cfdata);
}
This link is hint for me that how to update your image..
http://davidbits.blogspot.in/2010/01/iphone-update-addressbook-contact.html
declare 1 object in .h file
NSInteger recordID;
then open contact list and for fetching the contact we use this method
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {
recordID = ABRecordGetRecordID(person);
name = [(NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty) autorelease];
lblName.text = name;
if(ABPersonHasImageData(person)) {
CFDataRef imageData = ABPersonCopyImageData(person);
your uiimage = [UIImage imageWithData:(NSData *)imageData];
you uiimageview.image = your uiimage;
CFRelease(imageData);
} else {
you uiimageview.image = [UIImage imageNamed:#"ABPicturePerson#2x.png"];
}
[self.navigationController dismissViewControllerAnimated:(YES) completion:nil];
//[self.navigationController dismissModalViewControllerAnimated:YES];
return NO;
}
then write action for save detail or update detail
-(IBAction)btnSaveClicked
{
CFErrorRef *aberror = NULL;
ABRecordRef aRecord = ABAddressBookGetPersonWithRecordID(addressBook, recordID);
if (aRecord) {
NSData *dataRef = UIImagePNGRepresentation(your uiimage);
ABPersonSetImageData(aRecord, (CFDataRef)dataRef, nil);
}
ABAddressBookSave(addressBook, aberror);
//BOOL didAdd = ABAddressBookSave(addressBook, nil);
CFRelease(addressBook);
}
sure you will get result..
Use ABRecordRef person when you want to update:
Firstly create ABAddressBookRef:
// Request authorization to Address Book
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
Now check person has image:
if(ABPersonHasImageData(person))
{
//remove image as we want to update to new image
NSError *anError;
if(ABPersonRemoveImageData(person, &anError))
NSLog(#"removed");
else
NSLog(#"%#",[anError description]);
}
Update
UIImage *image = image here;
NSData *picData = UIImageJPEGRepresentation(image, 0.9f);
ABPersonSetImageData(person, (CFDataRef)picData, nil);
call saving function:
ABAddressBookSave(addressBookRef, nil);