如何使用CNContactVCardSerialization dataWithContacts:方法获取联系人图像的VCF数据?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (213)

我正在使用CNContacts和CNContactUI框架并通过此选择联系人

CNContactPickerViewController *contactPicker = [CNContactPickerViewController new];
              contactPicker.delegate = self;
 [self presentViewController:contactPicker animated:YES completion:nil];

-(void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact
{
    NSArray *array = [[NSArray alloc] initWithObjects:contact, nil];
    NSError *error;
    NSData *data = [CNContactVCardSerialization dataWithContacts:array error:&error];
    NSLog(@"ERROR_IF_ANY :: %@",error.description);
}

联系对象具有contact.imageData和日志。但当我试图通过交叉检查这些数据

NSArray *contactList = [NSArray arrayWithArray:[CNContactVCardSerialization contactsWithData:data error:nil]];
CNContact *contactObject = [contactList objectAtIndex:0];

这是空的:

//contactObject.imageData  

为什么我收到此null并且此联系人在签入联系人时有图像?

提问于
用户回答回答于

作为一种解决方法,您可以在VCard中创建PHOTO字段。

NSError* error = nil;
NSData* vCardData = [CNContactVCardSerialization dataWithContacts:@[contact] error:&error];
NSString* vcString = [[NSString alloc] initWithData:vCardData encoding:NSUTF8StringEncoding];
NSString* base64Image = contact.imageData.base64Encoding;
NSString* vcardImageString = [[@"PHOTO;TYPE=JPEG;ENCODING=BASE64:" stringByAppendingString:base64Image] stringByAppendingString:@"\n"];
vcString = [vcString stringByReplacingOccurrencesOfString:@"END:VCARD" withString:[vcardImageString stringByAppendingString:@"END:VCARD"]];
vCardData = [vcString dataUsingEncoding:NSUTF8StringEncoding];

由于某些原因,CNContactVCardSerialization不使用任何联系人照片。序列化后的VCard看起来像:

BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iPhone OS 9.3.2//EN
N:Contact;Test;;;
FN: Test  Contact 
END:VCARD

在VCard中插入PHOTO字段后,您将获得

BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iPhone OS 9.3.2//EN
N:Contact;Test;;;
FN: Test  Contact 
PHOTO;TYPE=JPEG;ENCODING=BASE64:<photo base64 string>
END:VCARD

在此插入之后,联系人在CNContactViewController中看起来很好

用户回答回答于

我想改进和改进现代化的Swift 3,这是kudinovdenis的优秀答案。

只需将以下扩展名放入您的项目中即可

import Foundation
import Contacts

extension CNContactVCardSerialization {
    internal class func vcardDataAppendingPhoto(vcard: Data, photoAsBase64String photo: String) -> Data? {
        let vcardAsString = String(data: vcard, encoding: .utf8)
        let vcardPhoto = "PHOTO;TYPE=JPEG;ENCODING=BASE64:".appending(photo)
        let vcardPhotoThenEnd = vcardPhoto.appending("\nEND:VCARD")
        if let vcardPhotoAppended = vcardAsString?.replacingOccurrences(of: "END:VCARD", with: vcardPhotoThenEnd) {
            return vcardPhotoAppended.data(using: .utf8)
        }
        return nil

    }
    class func data(jpegPhotoContacts: [CNContact]) throws -> Data {
        var overallData = Data()
        for contact in jpegPhotoContacts {
            let data = try CNContactVCardSerialization.data(with: [contact])
            if contact.imageDataAvailable {
                if let base64imageString = contact.imageData?.base64EncodedString(),
                    let updatedData = vcardDataAppendingPhoto(vcard: data, photoAsBase64String: base64imageString) {
                    overallData.append(updatedData)
                }
            } else {
                overallData.append(data)
            }
        }
        return overallData
    }
}

然后您可以使用它类似于现有的序列化方法:

CNContactVCardSerialization.data(jpegPhotoContacts: [contact1, contact2])

请注意,这需要进行序列化,如果您还要导入,则需要编写类似的反序列化方法。

所属标签

可能回答问题的人

  • 不吃貓的鱼oo

    5 粉丝466 提问6 回答
  • Richel

    8 粉丝0 提问4 回答
  • 发条丶魔灵1

    6 粉丝525 提问3 回答
  • 人生的旅途

    10 粉丝484 提问3 回答

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励