导出 VCard 中的图片 Swift
Export Picture in VCard Swift
我正在尝试开发一个应用程序,该应用程序从用户那里输入有关联系人的某些字段,然后将该联系人导出为 VCard。我可以成功导出联系人,但是当我尝试使用位于 iCloud.com 的联系人导入联系人时,图片没有被导入。
正在导入所有其他信息,但不导入图片。
我尝试了两种导出 VCard 的方法。
先到这里
public func getVCard() -> Data?{
var contact = CNMutableContact()
let homeEmail = CNLabeledValue(label:CNLabelHome, value:self.email as! NSString)
contact.emailAddresses = [homeEmail]
let phone = CNLabeledValue(label: CNLabelPhoneNumberMobile, value:CNPhoneNumber(stringValue: self.phone!))
contact.phoneNumbers = [phone]
contact.givenName = self.name!
if let d = self.data{
contact.imageData = d
}
let address = CNMutablePostalAddress()
address.country = self.address!
contact.postalAddresses = [CNLabeledValue(label: CNLabelHome, value: address)]
contact.organizationName = self.company!
contact.jobTitle = title!
let sc1 = CNSocialProfile(urlString: "\(socialMedia1!)", username: self.name!, userIdentifier: self.name!, service: CNContactSocialProfilesKey)
let sc2 = CNSocialProfile(urlString: "\(socialMedia2!)", username: self.name!, userIdentifier: self.name!, service: CNContactSocialProfilesKey)
//contact.socialProfiles = [CNSocialProfile(]
let sc3 = CNSocialProfile(urlString: "\(socialMedia3!)", username: self.name!, userIdentifier: self.name!, service: CNContactSocialProfilesKey)
contact.socialProfiles = [CNLabeledValue(label: "Profile1", value: sc1), CNLabeledValue(label: "Profile2", value: sc2), CNLabeledValue(label: "Profile3", value: sc3)]
contact.note = self.notes!
let urlAddresses = CNLabeledValue(label: CNLabelURLAddressHomePage, value: self.web as! NSString)
contact.urlAddresses = [urlAddresses]
var data: Data?
do{
data = try CNContactVCardSerialization.data(with: [contact])
}catch let error{
print(error.localizedDescription)
}
return data
}
当我调试此功能时,我可以在联系人对象中看到图片数据,但是当导出该 VCard 并尝试在 iCloud.com 上导入它时,它不会导入该联系人的图片。
现在我用来导出联系人的第二种方法如下,我更喜欢使用这种方法的答案,因为这是最适合我的。
func textBasedVCard()-> Data?{
var string = "BEGIN:VCARD\nVERSION:3.0\n"
string += "N:\(self.name!);\nFN:\(self.name!)\nORG:\(self.company!)\nTITLE:\(self.title!)\nTEL;TYPE=WORK,VOICE:\(self.phone!)\nADR;TYPE=WORK:;;\(self.address!)\nNOTE:\(self.notes!)\nitem1.URL:\(self.web!)\nitem2.URL:\(self.blog!)\nitem3.URL:\(self.socialMedia1!)\nitem4.URL:\(self.socialMedia2!)\nitem5.URL:\(self.socialMedia3!)\nEMAIL;TYPE=PREF,INTERNET:\(self.email!)\nEND:VCARD"
print(string)
let utf8str = string.data(using: String.Encoding.utf8)
//utf8str?.base64EncodedStringWithOptions(NSData.Base64EncodingOptions(rawValue: 0))
if let base64Encoded = utf8str?.base64EncodedString(options: .init(rawValue: 0))
{
return Data(base64Encoded: base64Encoded)!
}
return nil
}
在这种方法中我不知道如何附加图片数据。请指导我解决这个问题。我将不胜感激。谢谢
编辑:
这个问题绝不是任何其他问题的重复。你可以看到 link 自己为了让自己感到自豪而发布的自己。
来自上面发布的回复 (ABPersonCreatePeopleInSourceWithVCardRepresentation):
Address Book supports vCard version 3.0.
VCARD > PHOTO - An image or photograph of the individual associated with the vCard. It may point to an external URL or may be embedded in the vCard as a Base64 encoded block of text.
2.1: PHOTO;JPEG:http://example.com/photo.jpg
2.1: PHOTO;JPEG;ENCODING=BASE64:[base64-data]
3.0: PHOTO;TYPE=JPEG;VALUE=URI:http://example.com/photo.jpg
=> 3.0: PHOTO;TYPE=JPEG;ENCODING=b:[base64-data] // Works in iOS/macOS
4.0: PHOTO;MEDIATYPE=image/jpeg:http://example.com/photo.jpg
4.0: PHOTO:data:image/jpeg;base64,[base64-data]
如何为 iOS/macOS
创建 VCF 3.0 卡
测试显示第二种方法有效:使用 base64 对 JPEG 照片进行编码。
PHOTO;ENCODING=b;TYPE=JPEG:\(base64EncodedImage)
工作 PoC:
struct VCFBuilder {
private let name: String? = "Name1"
private let company: String? = "Company"
private let title: String? = "Title1"
private let phone: String? = "555-1234-1234"
private let address: String? = "aaa"
private let notes: String? = "PROnotes"
private let web: String? = "web"
private let blog: String? = "bolgg"
private let socialMedia1: String? = "social1"
private let socialMedia2: String? = "social2"
private let socialMedia3: String? = "social3"
private let email: String? = "email@mail.com"
private let imageUrl: String? = "http://0.gravatar.com/avatar/3f009d72559f51e7e454b16e5d0687a1"
func vcf() -> String? {
do {
let url = URL(string: self.imageUrl!)
let data = try Data(contentsOf: url!).base64EncodedString()
return generateVCF(withEncodedImage: data)
} catch {
print(error)
return nil
}
}
// TODO: Don't !
private func generateVCF(withEncodedImage imageBase64: String) -> String {
return """
BEGIN:VCARD
VERSION:3.0
N:\(self.name!);
FN:\(self.name!)
ORG:\(self.company!)
TITLE:\(self.title!)
TEL;TYPE=WORK,VOICE:\(self.phone!)
ADR;TYPE=WORK:;;\(self.address!)
NOTE:\(self.notes!)
PHOTO;ENCODING=b;TYPE=JPEG:\(imageBase64)
item1.URL:\(self.web!)
item2.URL:\(self.blog!)
item3.URL:\(self.socialMedia1!)
item4.URL:\(self.socialMedia2!)
item5.URL:\(self.socialMedia3!)
EMAIL;TYPE=PREF,INTERNET:\(self.email!)
END:VCARD
"""
}
}
let vcf = VCFBuilder().vcf()
print(vcf)
如何在iOS/macOS中导入VCF 3.0卡:
- 手动使用 Contacts.app
- iOS <= 9:
ABPersonCreatePeopleInSourceWithVCardRepresentation(_:_:)
(docs)
- iOS >= 9:
CNContactVCardSerialization.contacts(with:)
(docs)
guard let data = VCFBuilder().vcf()?.data(using: .utf8),
let contact = try? CNContactVCardSerialization.contacts(with: data).first
else { return }
print(contact.imageData!.base64EncodedString())
使用 iOS' 导入 Contacts.app:
我正在尝试开发一个应用程序,该应用程序从用户那里输入有关联系人的某些字段,然后将该联系人导出为 VCard。我可以成功导出联系人,但是当我尝试使用位于 iCloud.com 的联系人导入联系人时,图片没有被导入。 正在导入所有其他信息,但不导入图片。
我尝试了两种导出 VCard 的方法。
先到这里
public func getVCard() -> Data?{
var contact = CNMutableContact()
let homeEmail = CNLabeledValue(label:CNLabelHome, value:self.email as! NSString)
contact.emailAddresses = [homeEmail]
let phone = CNLabeledValue(label: CNLabelPhoneNumberMobile, value:CNPhoneNumber(stringValue: self.phone!))
contact.phoneNumbers = [phone]
contact.givenName = self.name!
if let d = self.data{
contact.imageData = d
}
let address = CNMutablePostalAddress()
address.country = self.address!
contact.postalAddresses = [CNLabeledValue(label: CNLabelHome, value: address)]
contact.organizationName = self.company!
contact.jobTitle = title!
let sc1 = CNSocialProfile(urlString: "\(socialMedia1!)", username: self.name!, userIdentifier: self.name!, service: CNContactSocialProfilesKey)
let sc2 = CNSocialProfile(urlString: "\(socialMedia2!)", username: self.name!, userIdentifier: self.name!, service: CNContactSocialProfilesKey)
//contact.socialProfiles = [CNSocialProfile(]
let sc3 = CNSocialProfile(urlString: "\(socialMedia3!)", username: self.name!, userIdentifier: self.name!, service: CNContactSocialProfilesKey)
contact.socialProfiles = [CNLabeledValue(label: "Profile1", value: sc1), CNLabeledValue(label: "Profile2", value: sc2), CNLabeledValue(label: "Profile3", value: sc3)]
contact.note = self.notes!
let urlAddresses = CNLabeledValue(label: CNLabelURLAddressHomePage, value: self.web as! NSString)
contact.urlAddresses = [urlAddresses]
var data: Data?
do{
data = try CNContactVCardSerialization.data(with: [contact])
}catch let error{
print(error.localizedDescription)
}
return data
}
当我调试此功能时,我可以在联系人对象中看到图片数据,但是当导出该 VCard 并尝试在 iCloud.com 上导入它时,它不会导入该联系人的图片。
现在我用来导出联系人的第二种方法如下,我更喜欢使用这种方法的答案,因为这是最适合我的。
func textBasedVCard()-> Data?{
var string = "BEGIN:VCARD\nVERSION:3.0\n"
string += "N:\(self.name!);\nFN:\(self.name!)\nORG:\(self.company!)\nTITLE:\(self.title!)\nTEL;TYPE=WORK,VOICE:\(self.phone!)\nADR;TYPE=WORK:;;\(self.address!)\nNOTE:\(self.notes!)\nitem1.URL:\(self.web!)\nitem2.URL:\(self.blog!)\nitem3.URL:\(self.socialMedia1!)\nitem4.URL:\(self.socialMedia2!)\nitem5.URL:\(self.socialMedia3!)\nEMAIL;TYPE=PREF,INTERNET:\(self.email!)\nEND:VCARD"
print(string)
let utf8str = string.data(using: String.Encoding.utf8)
//utf8str?.base64EncodedStringWithOptions(NSData.Base64EncodingOptions(rawValue: 0))
if let base64Encoded = utf8str?.base64EncodedString(options: .init(rawValue: 0))
{
return Data(base64Encoded: base64Encoded)!
}
return nil
}
在这种方法中我不知道如何附加图片数据。请指导我解决这个问题。我将不胜感激。谢谢
编辑:
这个问题绝不是任何其他问题的重复。你可以看到 link 自己为了让自己感到自豪而发布的自己。
来自上面发布的回复 (ABPersonCreatePeopleInSourceWithVCardRepresentation):
Address Book supports vCard version 3.0.
VCARD > PHOTO - An image or photograph of the individual associated with the vCard. It may point to an external URL or may be embedded in the vCard as a Base64 encoded block of text.
2.1: PHOTO;JPEG:http://example.com/photo.jpg
2.1: PHOTO;JPEG;ENCODING=BASE64:[base64-data]
3.0: PHOTO;TYPE=JPEG;VALUE=URI:http://example.com/photo.jpg
=> 3.0: PHOTO;TYPE=JPEG;ENCODING=b:[base64-data] // Works in iOS/macOS
4.0: PHOTO;MEDIATYPE=image/jpeg:http://example.com/photo.jpg
4.0: PHOTO:data:image/jpeg;base64,[base64-data]
如何为 iOS/macOS
创建 VCF 3.0 卡测试显示第二种方法有效:使用 base64 对 JPEG 照片进行编码。
PHOTO;ENCODING=b;TYPE=JPEG:\(base64EncodedImage)
工作 PoC:
struct VCFBuilder {
private let name: String? = "Name1"
private let company: String? = "Company"
private let title: String? = "Title1"
private let phone: String? = "555-1234-1234"
private let address: String? = "aaa"
private let notes: String? = "PROnotes"
private let web: String? = "web"
private let blog: String? = "bolgg"
private let socialMedia1: String? = "social1"
private let socialMedia2: String? = "social2"
private let socialMedia3: String? = "social3"
private let email: String? = "email@mail.com"
private let imageUrl: String? = "http://0.gravatar.com/avatar/3f009d72559f51e7e454b16e5d0687a1"
func vcf() -> String? {
do {
let url = URL(string: self.imageUrl!)
let data = try Data(contentsOf: url!).base64EncodedString()
return generateVCF(withEncodedImage: data)
} catch {
print(error)
return nil
}
}
// TODO: Don't !
private func generateVCF(withEncodedImage imageBase64: String) -> String {
return """
BEGIN:VCARD
VERSION:3.0
N:\(self.name!);
FN:\(self.name!)
ORG:\(self.company!)
TITLE:\(self.title!)
TEL;TYPE=WORK,VOICE:\(self.phone!)
ADR;TYPE=WORK:;;\(self.address!)
NOTE:\(self.notes!)
PHOTO;ENCODING=b;TYPE=JPEG:\(imageBase64)
item1.URL:\(self.web!)
item2.URL:\(self.blog!)
item3.URL:\(self.socialMedia1!)
item4.URL:\(self.socialMedia2!)
item5.URL:\(self.socialMedia3!)
EMAIL;TYPE=PREF,INTERNET:\(self.email!)
END:VCARD
"""
}
}
let vcf = VCFBuilder().vcf()
print(vcf)
如何在iOS/macOS中导入VCF 3.0卡:
- 手动使用 Contacts.app
- iOS <= 9:
ABPersonCreatePeopleInSourceWithVCardRepresentation(_:_:)
(docs) - iOS >= 9:
CNContactVCardSerialization.contacts(with:)
(docs)
guard let data = VCFBuilder().vcf()?.data(using: .utf8),
let contact = try? CNContactVCardSerialization.contacts(with: data).first
else { return }
print(contact.imageData!.base64EncodedString())
使用 iOS' 导入 Contacts.app: