在VCard Swift中导出图片

时间:2017-07-26 20:16:51

标签: ios swift xcode vcard

我正在尝试开发一个应用程序,该应用程序从用户输入一些关于联系人的字段,然后将该联系人导出为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
}

在这种方法中,我不知道如何附加图片数据。请指导我解决这个问题。我将非常感激。感谢。

修改

这个问题绝不是任何其他问题的重复。您可以亲自看到自己发布的链接,让自己感到自豪。

1 个答案:

答案 0 :(得分:3)

从上面发布的回复(ABPersonCreatePeopleInSourceWithVCardRepresentation):

  

地址簿支持vCard 3.0版。

     

VCARD>照片 - 与vCard关联的个人的图像或照片。它可以指向外部URL,也可以作为Base64编码的文本块嵌入到vCard中。

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:

导入

enter image description here