// MARK: ios9之后的通讯录转Vcard(版本3.0)字符串
+(NSString*)generateVCard30StringWithContacts:(NSArray<CNContact *> *)contacts {
NSInteger counter = 0;
NSString *vcard = @"";
for(CFIndex i = 0; i < contacts.count; i++) {
CNContact *contact = contacts[i];
NSString *firstName = contact.givenName;
firstName = (firstName ?
firstName : @"");
NSString *lastName = contact.familyName;
lastName = (lastName ? lastName : @"");
NSString *middleName = contact.middleName;
NSString *prefix = contact.namePrefix;
NSString *suffix = contact.nameSuffix;
NSString *nickName = contact.nickname;
NSString *firstNamePhonetic = contact.phoneticGivenName;
NSString *lastNamePhonetic = contact.phoneticFamilyName;
NSString *organization = contact.organizationName;
NSString *jobTitle = contact.jobTitle;
NSString *department = contact.departmentName;
NSString *compositeName = [NSString stringWithFormat:@"%@%@",firstName,lastName];
if(i > 0) {
vcard = [vcard stringByAppendingFormat:@"\n"];
}
vcard = [vcard stringByAppendingFormat:@"BEGIN:VCARD\nVERSION:2.1\nN:%@;%@;%@;%@;%@\n",
(firstName ?
firstName : @""),
(lastName ? lastName : @""),
(middleName ? middleName : @""),
(prefix ?
prefix : @""),
(suffix ? suffix : @"")
];
vcard = [vcard stringByAppendingFormat:@"FN:%@\n",compositeName];
if(nickName) vcard = [vcard stringByAppendingFormat:@"NICKNAME:%@\n",nickName];
if(firstNamePhonetic) vcard = [vcard stringByAppendingFormat:@"X-PHONETIC-FIRST-NAME:%@\n",firstNamePhonetic];
if(lastNamePhonetic) vcard = [vcard stringByAppendingFormat:@"X-PHONETIC-LAST-NAME:%@\n",lastNamePhonetic];
// Work
if(organization) vcard = [vcard stringByAppendingFormat:@"ORG:%@;%@\n",(organization?
organization:@""),(department?department:@"")];
if(jobTitle) vcard = [vcard stringByAppendingFormat:@"TITLE:%@\n",jobTitle];
// Mail
if(contact.emailAddresses.count > 0) {
for (int k = 0; k < contact.emailAddresses.count; k++) {
CNLabeledValue<NSString*>* emailObject = contact.emailAddresses[k];
NSString *label = emailObject.label;
NSString *email = emailObject.value;
NSString *labelLower = [label lowercaseString];
vcard = [vcard stringByAppendingFormat:@"EMAIL;type=INTERNET;type=WORK:%@\n",email];
if ([labelLower isEqualToString:@"home"]) vcard = [vcard stringByAppendingFormat:@"EMAIL;type=INTERNET;type=HOME:%@\n",email];
else if ([labelLower isEqualToString:@"work"]) vcard = [vcard stringByAppendingFormat:@"EMAIL;type=INTERNET;type=WORK:%@\n",email];
else {//类型解析不出来的
counter++;
vcard = [vcard stringByAppendingFormat:@"item%li.EMAIL;type=INTERNET:%@\nitem%li.X-ABLabel:%@\n",(long)counter,email,(long)counter,label];
}
}
}
// Tel
if(contact.phoneNumbers.count > 0) {
for (int k = 0; k < contact.phoneNumbers.count; k++) {
CNLabeledValue<CNPhoneNumber*>* phoneObject = contact.phoneNumbers[k];
NSString *label = phoneObject.label;
NSString *number = [phoneObject.value stringValue];
NSString *labelLower = [label lowercaseString];
if ([labelLower isEqualToString:@"mobile"]) vcard = [vcard stringByAppendingFormat:@"TEL;type=CELL:%@\n",number];
else if ([labelLower isEqualToString:@"home"]) vcard = [vcard stringByAppendingFormat:@"TEL;type=HOME:%@\n",number];
else if ([labelLower isEqualToString:@"work"]) vcard = [vcard stringByAppendingFormat:@"TEL;type=WORK:%@\n",number];
else if ([labelLower isEqualToString:@"main"]) vcard = [vcard stringByAppendingFormat:@"TEL;type=MAIN:%@\n",number];
else if ([labelLower isEqualToString:@"homefax"]) vcard = [vcard stringByAppendingFormat:@"TEL;type=HOME;type=FAX:%@\n",number];
else if ([labelLower isEqualToString:@"workfax"]) vcard = [vcard stringByAppendingFormat:@"TEL;type=WORK;type=FAX:%@\n",number];
else if ([labelLower isEqualToString:@"pager"]) vcard = [vcard stringByAppendingFormat:@"TEL;type=PAGER:%@\n",number];
else if([labelLower isEqualToString:@"other"]) vcard = [vcard stringByAppendingFormat:@"TEL;type=OTHER:%@\n",number];
else { //类型解析不出来的
counter++;
vcard = [vcard stringByAppendingFormat:@"item%li.TEL:%@\nitem%li.X-ABLabel:%@\n",(long)counter,number,(long)counter,label];
}
}
}
// Address
if(contact.postalAddresses.count > 0) {
for (int k = 0; k < contact.postalAddresses.count; k++) {
CNLabeledValue<CNPostalAddress*>* addressObject = contact.postalAddresses[k];
NSString *label = addressObject.label;
CNPostalAddress *address = addressObject.value;
NSString *labelLower = [label lowercaseString];
NSString* country = address.country;
NSString* city = address.city;
NSString* state = address.state;
NSString* street = address.street;
NSString* zip = address.postalCode;
NSString* countryCode = address.ISOCountryCode;
NSString *type = @"";
NSString *labelField = @"";
counter++;
if([labelLower isEqualToString:@"work"]) type = @"WORK";
else if([labelLower isEqualToString:@"home"]) type = @"HOME";
else if(label && [label length] > 0)
{
labelField = [NSString stringWithFormat:@"item%li.X-ABLabel:%@\n",(long)counter,label];
}
vcard = [vcard stringByAppendingFormat:@"item%li.ADR;type=%@:;;%@;%@;%@;%@;%@\n%@item%li.X-ABADR:%@\n",
(long)counter,
type,
(street ? street : @""),
(city ? city : @""),
(state ? state : @""),
(zip ? zip : @""),
(country ? country : @""),
labelField,
(long)counter,
(countryCode ?
countryCode : @"")
];
}
}
// 剩下的不经常使用,我就不写了,要是须要。自己补全
// url
// TODO:
// IM
// TODO:
// Photo
// TODO:
if (contact.imageData != nil) {
NSString *imageBase64Str = [contact.imageData base64EncodedStringWithOptions: NSDataBase64EncodingEndLineWithLineFeed];
vcard = [vcard stringByAppendingFormat:@"PHOTO:<TYPE>image/jpg</TYPE><BINVAL>%@</BINVAL>\n", imageBase64Str];
}
vcard = [vcard stringByAppendingString:@"END:VCARD"];
}
return vcard;
}
// MARK: ios9之后的通讯录转Vcard(版本2.1)字符串
+(NSString*)generateVCard21StringWithContacts:(NSArray<CNContact *> *)contacts {
NSInteger counter = 0;
NSString *vcard = @"";
for(CFIndex i = 0; i < contacts.count; i++) {
CNContact *contact = contacts[i];
NSString *firstName = contact.givenName;
firstName = (firstName ?
firstName : @"");
NSString *lastName = contact.familyName;
lastName = (lastName ? lastName : @"");
NSString *middleName = contact.middleName;
NSString *prefix = contact.namePrefix;
NSString *suffix = contact.nameSuffix;
// 编码
firstName = [NSString stringAddEncodeWithString:firstName];
lastName = [NSString stringAddEncodeWithString:lastName];
middleName = [NSString stringAddEncodeWithString:middleName];
// NSString *nickName = contact.nickname;
// NSString *firstNamePhonetic = contact.phoneticGivenName;
// NSString *lastNamePhonetic = contact.phoneticFamilyName;
// NSString *organization = contact.organizationName;
// NSString *jobTitle = contact.jobTitle;
// NSString *department = contact.departmentName;
NSString *compositeName = [NSString stringWithFormat:@"%@%@",firstName,lastName];
if(i > 0) {
vcard = [vcard stringByAppendingFormat:@"\n"];
}
vcard = [vcard stringByAppendingFormat:@"BEGIN:VCARD\nVERSION:2.1\nN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:%@;%@;%@;%@;%@\n",
(firstName ?
firstName : @""),
(lastName ? lastName : @""),
(middleName ? middleName : @""),
(prefix ?
prefix : @""),
(suffix ? suffix : @"")
];
vcard = [vcard stringByAppendingFormat:@"FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:%@\n",compositeName];
// Tel
if(contact.phoneNumbers.count > 0) {
for (int k = 0; k < contact.phoneNumbers.count; k++) {
CNLabeledValue<CNPhoneNumber*>* phoneObject = contact.phoneNumbers[k];
NSString *label = phoneObject.label;
NSString *number = [phoneObject.value stringValue];
NSString *labelLower = [label lowercaseString];
labelLower = [labelLower stringByReplacingOccurrencesOfString:@"_$!<" withString:@""];
labelLower = [labelLower stringByReplacingOccurrencesOfString:@">!$_" withString:@""];
if ([labelLower isEqualToString:@"mobile"]) vcard = [vcard stringByAppendingFormat:@"TEL;CELL:%@\n",number];
else if ([labelLower isEqualToString:@"home"]) vcard = [vcard stringByAppendingFormat:@"TEL;HOME:%@\n",number];
else if ([labelLower isEqualToString:@"work"]) vcard = [vcard stringByAppendingFormat:@"TEL;WORK:%@\n",number];
else if ([labelLower isEqualToString:@"main"]) vcard = [vcard stringByAppendingFormat:@"TEL;MAIN:%@\n",number];
else if ([labelLower isEqualToString:@"homefax"]) vcard = [vcard stringByAppendingFormat:@"TEL;HOME;type=FAX:%@\n",number];
else if ([labelLower isEqualToString:@"workfax"]) vcard = [vcard stringByAppendingFormat:@"TEL;WORK;FAX:%@\n",number];
else if ([labelLower isEqualToString:@"pager"]) vcard = [vcard stringByAppendingFormat:@"TEL;PAGER:%@\n",number];
else if([labelLower isEqualToString:@"other"]) vcard = [vcard stringByAppendingFormat:@"TEL;OTHER:%@\n",number];
else { //类型解析不出来的
counter++;
// vcard = [vcard stringByAppendingFormat:@"item%i.TEL:%@\nitem%i.X-ABLabel:%@\n",counter,number,counter,label];
}
}
}
// Mail
if(contact.emailAddresses.count > 0) {
for (int k = 0; k < contact.emailAddresses.count; k++) {
CNLabeledValue<NSString*>* emailObject = contact.emailAddresses[k];
NSString *label = emailObject.label;
NSString *email = emailObject.value;
NSString *labelLower = [label lowercaseString];
vcard = [vcard stringByAppendingFormat:@"EMAIL;WORK:%@\n",email];
if ([labelLower isEqualToString:@"home"]) vcard = [vcard stringByAppendingFormat:@"EMAIL;HOME:%@\n",email];
else if ([labelLower isEqualToString:@"work"]) vcard = [vcard stringByAppendingFormat:@"EMAIL;WORK:%@\n",email];
else {//类型解析不出来的
counter++;
// vcard = [vcard stringByAppendingFormat:@"item%i.EMAIL;type=INTERNET:%@\nitem%i.X-ABLabel:%@\n",counter,email,counter,label];
}
}
}
// Address
if(contact.postalAddresses.count > 0) {
for (int k = 0; k < contact.postalAddresses.count; k++) {
CNLabeledValue<CNPostalAddress*>* addressObject = contact.postalAddresses[k];
NSString *label = addressObject.label;
CNPostalAddress *address = addressObject.value;
NSString *labelLower = [label lowercaseString];
NSString* country = address.country;
NSString* city = address.city;
NSString* state = address.state;
NSString* street = address.street;
NSString* zip = address.postalCode;
// NSString* countryCode = address.ISOCountryCode;
NSString *type = @"";
NSString *labelField = @"";
counter++;
if([labelLower isEqualToString:@"work"]) type = @"WORK";
else if([labelLower isEqualToString:@"home"]) type = @"HOME";
else if(label && [label length] > 0)
{
labelField = [NSString stringWithFormat:@"item%li.X-ABLabel:%@\n",(long)counter,label];
}
vcard = [vcard stringByAppendingFormat:@"ADR;%@:;;%@;%@;%@;%@;%@\n",
type,
(street ? street : @""),
(city ? city : @""),
(state ? state : @""),
(zip ? zip : @""),
(country ? country : @"")];
}
}
// 剩下的不经常使用,我就不写了,要是须要。自己补全
// url
// TODO:
// IM
// TODO:
// Photo
// TODO:
if (contact.imageDataAvailable) {
NSString *imageBase64Str = [contact.imageData base64EncodedStringWithOptions: NSDataBase64EncodingEndLineWithLineFeed];
vcard = [vcard stringByAppendingFormat:@"PHOTO;ENCODING=BASE64;JPEG:%@\n", imageBase64Str];
}
vcard = [vcard stringByAppendingString:@"END:VCARD"];
}
return vcard;
}
// 写字符串到文件中
+ (NSString *)writeStringToFile:(NSString *)writeStr andFileSuffix:(NSString *)fileType {
// 获取带毫秒的时间戳
NSDate *datenow = [NSDate date];
NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)([datenow timeIntervalSince1970]*1000)];
NSString *writePath = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"tmp/%@.%@", timeSp, fileType]];
NSError *error;
[writeStr writeToFile:writePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (error) {
NSLog(@"导出失败");
return nil;
}else {
NSLog(@"导出成功");
return writePath;
}
}
2. Vcard类型的文件(.vcf)解析成iOS中的CNContact
// responseObject = URL.init(fileURLWithPath: "/var/***/contacts.vcf")
let tempData = try? Data.init(contentsOf: responseObject as! URL)
let vcardStr = String.init(data: tempData!, encoding: String.Encoding.utf8)
let vcardstr2 = NSString.init(replaceEncodeWith: vcardStr)
let goalData = vcardstr2?.data(using: String.Encoding.utf8.rawValue)
let contacts = try? CNContactVCardSerialization.contacts(with: goalData!)