You are creating the data wrong - you should be doing it like this.
UIImage *img = [UIImage imageWithContentsOfFile:path1];
NSData *dataRef = UIImagePNGRepresentation(img);
CFDataRef cfDataRef = CFDataCreate(NULL, [dataRef bytes], [dataRef length]);
Also try setting a break point somewhere in the beginning and check if something isn't nil or doesn't have wrong value.
UPDATE
I have tried it in actual Xcode, just to test. The reason why your code tells you that address book has no unsaved changes is because you haven't added the record inside it yet - otherwise you are setting an image on a contact that hasn't been added to address book yet (that is not a problem, you can do that without any problems, but the contact itself is not in the address book until you save it). So the magical line of code for you will probably be this:
ABAddressBookAddRecord(addressBook, person, &error);
This is the full code I've been using.
CFErrorRef error = nil;
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef person = ABPersonCreate();
NSString *path1 = [[NSBundle mainBundle] pathForResource:@"sky_main" ofType:@"jpg"];
UIImage *img = [UIImage imageWithContentsOfFile:path1];
NSData *dataRef = UIImagePNGRepresentation(img);
CFDataRef cfDataRef = CFDataCreate(NULL, [dataRef bytes], [dataRef length]);
if (ABPersonHasImageData(person)) {
ABPersonRemoveImageData(person, &error);
ABAddressBookSave(addressBook, &error);
}
ABAddressBookAddRecord(addressBook, person, &error);
if (ABPersonSetImageData(person, cfDataRef, &error)) {
if (ABAddressBookHasUnsavedChanges(addressBook)) {
NSLog(@"has unsaved changes");
} else {
NSLog(@"nothing to save");
}
if (ABAddressBookSave(addressBook, &error)) {
NSLog(@"saved");
} else {
NSLog(@"not saved");
}
}
ABUnknownPersonViewController *ctr = [[ABUnknownPersonViewController alloc] init];
ctr.unknownPersonViewDelegate = nil;
ctr.displayedPerson = person;
ctr.allowsAddingToAddressBook = YES;
ctr.allowsActions = YES;
ctr.hidesBottomBarWhenPushed = YES;
// [[[CCDirector sharedDirector] view] addSubview:ctr.view];
CFRelease(person);
CFRelease(addressBook);
I am also using the AddressBookUI, but you don't have to use it (I just wanted to see the changes to the unsaved contact).
UPDATE 2
Ok, just created a new project just to try. It looks like the problem was actually with the ABAddressBookRef. You have to get that from the peoplePicker argument of the delegate method. Since it is the delegate method you don't have to add the record because it already exists. This is the code that has to work (tried it 2 minutes ago). Let me know :)
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {
CFErrorRef error = nil;
ABAddressBookRef addressBook = peoplePicker.addressBook;
NSString *path1 = [[NSBundle mainBundle] pathForResource:@"cat" ofType:@"jpg"];
UIImage *img = [UIImage imageWithContentsOfFile:path1];
NSData *dataRef = UIImagePNGRepresentation(img);
CFDataRef cfDataRef = CFDataCreate(NULL, [dataRef bytes], [dataRef length]);
if (ABPersonHasImageData(person)) {
ABPersonRemoveImageData(person, &error);
ABAddressBookSave(addressBook, &error);
}
if (ABPersonSetImageData(person, cfDataRef, &error)) {
if (ABAddressBookHasUnsavedChanges(addressBook)) {
NSLog(@"has unsaved changes");
} else {
NSLog(@"nothing to save");
}
if (ABAddressBookSave(addressBook, &error)) {
NSLog(@"saved");
} else {
NSLog(@"not saved");
}
}
CFRelease(addressBook);
return YES;
}
Btw., since it is the delegate method do not release the person otherwise it will crash horribly - just kidding, it will crash, because it tries to access memory that doesn't exist.