3

我正在开发应用程序,当我从联系人选择器中选择任何联系人时,它会更改联系人的联系人图片。

这是我到目前为止实现的代码,

(BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
    CFErrorRef error=nil;
    ABAddressBookRef addressBook = ABAddressBookCreate();
    NSString *path1 = [[NSBundle mainBundle] pathForResource:@"birthday.jpg" ofType:nil];
    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))
    {
        NSLog(@"Set contact photo %@", error);

        if (ABAddressBookHasUnsavedChanges(addressBook))
        {
            NSLog(@"Changes made to address book");
        }
        else {
            NSLog(@"No changes made to address book");
        }
        if (ABAddressBookSave(addressBook, &error))
        {
            NSLog(@"Saved");
        }
        else {
            NSLog(@"Not saved");
        }       
    }

    CFRelease(cfDataRef);

    // TODO: release peoplePicker (and refactor code to not have it global)
    [self dismissModalViewControllerAnimated:YES];

    return NO;

}

但是当我调试并查看ABAddressBookHasUnsavedChanges它返回 false 并且图像未设置为联系人时。可能是什么原因?

我在shouldContinueAfterSelectingPerson;中写了这个方法 我检查了图像,它不是 null 并且ABPersonSetImageData正在返回TRUE

我已经更新了代码,已经检查了图像集,如果是,那么我将删除该图像并保存保存地址簿并重新发布 CFDataRef。

但它仍然无法正常工作

Update:2 
 I have edited the code , please look at the changes. 

我已经在这个方法中编写了所有代码
-(BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person { } ,
所以肯定会有人已经在地址簿中。但是我尝试根据上面的代码仍然认为 ABAddressBookHasUnsavedChanges 返回 false

4

1 回答 1

1

您正在创建错误的数据 - 您应该这样做。

UIImage *img = [UIImage imageWithContentsOfFile:path1];
NSData *dataRef = UIImagePNGRepresentation(img);
CFDataRef cfDataRef = CFDataCreate(NULL, [dataRef bytes], [dataRef length]);

还可以尝试在开头的某个地方设置一个断点,并检查是否有东西不是 nil 或没有错误的值。

更新

我已经在实际的 Xcode 中尝试过,只是为了测试。您的代码告诉您通讯录没有未保存的更改的原因是因为您尚未在其中添加记录 - 否则您正在为尚未添加到通讯录的联系人设置图像(那不是有问题,您可以毫无问题地执行此操作,但联系人本身在您保存之前不在通讯录中)。所以对你来说神奇的代码行可能是这样的:

ABAddressBookAddRecord(addressBook, person, &error);

这是我一直在使用的完整代码。

   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);

我也在使用 AddressBookUI,但您不必使用它(我只是想查看对未保存联系人的更改)。

更新 2

好的,刚刚创建了一个新项目只是为了尝试。看起来问题实际上出在 ABAddressBookRef 上。您必须从委托方法的 peoplePicker 参数中获取。由于它是委托方法,因此您不必添加记录,因为它已经存在。这是必须工作的代码(2 分钟前尝试过)。让我知道 :)

- (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;
}

顺便说一句,因为它是委托方法,所以不要释放这个人,否则它会严重崩溃——开玩笑,它会崩溃,因为它试图访问不存在的内存。

于 2013-07-19T13:35:46.903 回答