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

我正在使用CNContacts和CNContactUI框架,并通过这个select一个联系人

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

这是获取NULL //contactObject.imageData

需要帮助为什么我得到这个空,这个联系人有图像时检查联系人?

作为解决方法,您可以在VCard内创buildPHOTO字段。

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

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

对于N个联系人,可以使用下面的简单方法将图像数据添加到VCF中。

 -(NSData*)getVCFDataWithImagesFromContacts:(NSArray*)arrContacts { //---- Convert contacts array into VCF data. NSError *error; NSData *vcfData = [CNContactVCardSerialization dataWithContacts:arrContacts error:&error]; //--- Convert VCF data into string. NSString *strVCF = [[NSString alloc] initWithData:vcfData encoding:NSUTF8StringEncoding]; //--- Split contacts from VCF. NSMutableArray *arrSplit = (NSMutableArray*)[strVCF componentsSeparatedByString:@"END:VCARD"]; [arrSplit removeLastObject];//-- if object is "\r\n" otherwise comment this line. //--- Validate array count if (arrSplit.count == arrContacts.count) { for (int index=0;index<arrContacts.count;index++) { //--- Get current contact and VCF contact string. CNContact *contact = arrContacts[index]; NSString *strContact = arrSplit[index]; //--- Get base64 string of image. NSString* base64Image = [UIImagePNGRepresentation([ViewController imageWithImage:[UIImage imageWithData:contact.imageData] scaledToSize:CGSizeMake(50,50)]) base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]; //--- Append image tag into contact string. NSString* vcardImageString = [[@"PHOTO;ENCODING=BASE64;JPEG:" stringByAppendingString:base64Image] stringByAppendingString:@"\r\n"]; strContact = [strContact stringByAppendingString:[NSString stringWithFormat:@"%@%@",vcardImageString,@"END:VCARD\r\n"]]; //--- Update contact string from array. [arrSplit replaceObjectAtIndex:index withObject:strContact]; NSLog(@"strContact :%@",strContact); } } //--- Combine all contacts together in VCF. vcfData = [[arrSplit componentsJoinedByString:@""] dataUsingEncoding:NSUTF8StringEncoding]; strVCF = [[NSString alloc] initWithData:vcfData encoding:NSUTF8StringEncoding];//--- VCF Data NSLog(@"Contact VCF error :%@",error.localizedDescription); return vcfData; } +(UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize { UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0); [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; }