2017-08-01 15 views
0

エンコード/デコードSwiftのCNContactオブジェクトを一般的な方法でJSONエンコード/デコードしようとしています(これは、オブジェクトが実行時に保持するプロパティを判別したいという意味で、そのプロパティをハードコードしたくない)しかし、私はそうすることはできませんでした。私の質問は、スウィフト4でこの行動を達成する方法はありますか?もしそうなら、どうすればいいのですか?Swift CNContactオブジェクトを一般的に

+0

が希望のボタンアクションでこのコードを追加しますか? –

+0

すべてのCNContactオブジェクトが保持するすべてのプロパティを直列化して逆シリアル化したい...それはあなたの質問に答えますか? – mmarkus

答えて

1

いいえ、official documentationに従ってCNContactは変更されていないため、Encodeable & DecodableのタイプアライメントであるCodableプロトコルに準拠していません。 EncodableDecodableに現在準拠しているクラスのリストを見ることができます。CNContactもその中にはありません。

ただし、上記のプロトコルに準拠するようにCNContactの内線番号を書くことができます。

フレームワークを使用してCNContactオブジェクトをSwift3にエンコードする方法の例を次に示します。これは単なる例であり、可能なすべてのフィールドを解析しておらず、CNContactオブジェクトに特定の値が存在しない場合は、JSONにキーが存在しないことに注意してください。また、デコーダの機能は完全には実装されていませんが、エンコーダの動作を確認すれば簡単に実装できます。

JSONキーの名前も構造と一緒に任意に選択されていますので、それらを変更することができます。

以下のコードは、完全に動作するプレイグラウンドファイルです。必要に応じて、自分でテストすることができます。

import Contacts 

let contact = CNMutableContact() 
contact.birthday = DateComponents(calendar: Calendar.current,year: 1887, month: 1, day: 1) 
contact.contactType = CNContactType.person 
contact.givenName = "John" 
contact.familyName = "Appleseed" 

contact.imageData = Data() // The profile picture as a NSData object 

let homeEmail = CNLabeledValue(label:CNLabelHome, value: NSString(string: "[email protected]")) 
let workEmail = CNLabeledValue(label:CNLabelWork, value: NSString(string: "[email protected]")) 
contact.emailAddresses = [homeEmail, workEmail] 

contact.phoneNumbers = [CNLabeledValue(label:CNLabelPhoneNumberiPhone, value:CNPhoneNumber(stringValue:"(408) 555-0126"))] 

let homeAddress = CNMutablePostalAddress() 
homeAddress.street = "1 Infinite Loop" 
homeAddress.city = "Cupertino" 
homeAddress.state = "CA" 
homeAddress.postalCode = "95014" 
contact.postalAddresses = [CNLabeledValue(label:CNLabelHome, value:homeAddress)] 

func encodeContactToJson(contact: CNContact)->Data?{ 
    var contactDict = [String:Any]() 
    if let birthday = contact.birthday?.date { 
     let df = DateFormatter() 
     df.dateFormat = "yyyy-MM-dd" 
     contactDict["birthday"] = df.string(from: birthday) 
    } 
    contactDict["givenName"] = contact.givenName 
    contactDict["familyName"] = contact.familyName 
    if let imageData = contact.imageData { 
     contactDict["image"] = imageData.base64EncodedString() 
    } 
    if contact.emailAddresses.count > 0 { 
     var emailAddresses = [String:String]() 
     for (index, emailAddress) in contact.emailAddresses.enumerated() { 
      emailAddresses[emailAddress.label ?? "email\(index)"] = (emailAddress.value as String) 
     } 
     contactDict["emailAddresses"] = emailAddresses 
    } 
    if contact.phoneNumbers.count > 0 { 
     var phoneNumbers = [String:String]() 
     for (index, phoneNumber) in contact.phoneNumbers.enumerated() { 
      phoneNumbers[phoneNumber.label ?? "phone\(index)"] = phoneNumber.value.stringValue 
     } 
     contactDict["phoneNumbers"] = phoneNumbers 
    } 
    if contact.postalAddresses.count > 0 { 
     var postalAddresses = [String:String]() 
     for (index, postalAddress) in contact.postalAddresses.enumerated() { 
      postalAddresses[postalAddress.label ?? "postal\(index)"] = (CNPostalAddressFormatter.string(from: postalAddress.value, style: .mailingAddress)) 
     } 
     contactDict["postalAddresses"] = postalAddresses 
    } 
    return try? JSONSerialization.data(withJSONObject: contactDict) 
} 

func decodeContactsJson(jsonData: Data)->CNContact?{ 
    if let jsonDict = (try? JSONSerialization.jsonObject(with: jsonData)) as? [String:Any] { 
     let contact = CNMutableContact() 
     print(jsonDict) 
     return contact as CNContact 
    } else { 
     return nil 
    } 
} 

if let jsonContact = encodeContactToJson(contact: contact) { 
    print(decodeContactsJson(jsonData: jsonContact) ?? "Decoding failed") 
} else { 
    print("Encoding failed") 
} 
+0

ありがとうございました。私はすべてSwift開発経験はありませんが、CNContactの拡張機能のサンプルコードを提供できますか? – mmarkus

+0

私は現在Xcode9ベータ版をインストールしていないので、Swift4コードをコンパイルできず、コンパイルできないコードサンプルを提供したくありません。しかし、あなたが望むのであれば、 'Swift3 'で既に利用可能な' JSONSerialization'フレームワークを使って、それを行う方法の小さなサンプルをあなたに与えることができます。 –

+0

私は本当に感謝しています:) – mmarkus

0

シンプルなコンタクトピックを使用してください。

func contactViewController(_ viewController: CNContactViewController, didCompleteWith contact: CNContact?) { 

    var name = "" 
    var email = "" 
    var mobile = "" 
    var address = "" 
    var companyname = "" 
    var jobtitle = "" 
    var organization = "" 
    var workaddress = "" 
    var worknumber = "" 
    var personalurl = "" 
    var companyurl = "" 
    var otherurl = "" 
    var othernumber = "" 
    var otheraddress = "" 
    var homeemail = "" 
    var workemail = "" 
    var otheremail = "" 
    var dataAll = NSMutableArray() 

    if contact != nil 
    { 
     dataAll = NSMutableArray() 



     if (contact?.isKeyAvailable(CNContactGivenNameKey))! { 
      let name2 = contact?.familyName 
      name = (contact?.givenName)! + " " + name2! 

      UserDefaults.standard.set(name, forKey: "name") 


     } 



     if (contact?.isKeyAvailable(CNContactOrganizationNameKey))! 
     { 
      companyname = (contact?.organizationName)! 


      //var dic : NSDictionary = [:] 
      if companyname != "" { 
       let dic : [String : AnyObject] = ["name":companyname as AnyObject, 
                "type":"companyname" as AnyObject, 
                "typeof":"companyname" as AnyObject] 
       dataAll.add(dic) 
      } 



     } 

     let designation = contact?.jobTitle 

     if (designation?.isEmpty)! 
     { 

     } 
     else 
     { 
      jobtitle = designation! 
      //let dic : [String : AnyObject] = ["designation":jobtitle as AnyObject] 

      let dic : [String : AnyObject] = ["name":jobtitle as AnyObject, 
               "type":"designation" as AnyObject, 
               "typeof":"designation" as AnyObject 
      ] 
      dataAll.add(dic) 

     } 
     if (contact?.isKeyAvailable(CNContactPhoneNumbersKey))!{ 

      if (contact?.phoneNumbers.count == 0) 
      { 

      } 
      else 
      { 

       for phoneNumber:CNLabeledValue in (contact?.phoneNumbers)! { 
        let number = phoneNumber.value 

        let number2 = number.stringValue 


        let lable :String = CNLabeledValue<NSString>.localizedString(forLabel: phoneNumber.label!) 


        let dic : [String : AnyObject] = ["name":number2 as AnyObject, 
                 "type":lable as AnyObject, 
                 "typeof":"phonenumber" as AnyObject] 


        dataAll.add(dic) 


        if number2 != "" 
        { 

        } 


        if lable == "home" 
        { 
         if number2 == "" 
         { 

         } 
         else 
         { 
          mobile = number.stringValue 


          let number2 = String(mobile.digitsOnly())! 



         } 


        } 
        if lable == "work" 
        { 
         if number2 == "" 
         { 

         } 
         else 
         { 
          worknumber = number.stringValue 

         } 


        } 
        if lable == "mobile" 
        { 
         if number2 == "" 
         { 

         } 
         else 
         { 
          othernumber = number.stringValue 


         } 


        } 

       } 

      } 
     } 


     if (contact?.isKeyAvailable(CNContactEmailAddressesKey))! { 

      if (contact?.emailAddresses.count == 0) 
      { 

      } 
      else 
      { 

       for emaiadd:CNLabeledValue in (contact?.emailAddresses)! { 

        let name2 = (emaiadd.value as String) as String 

        if name2 != "" 
        { 
         UserDefaults.standard.set(emaiadd.value as String, forKey: "mainemail") 
        } 

        let lable :String = CNLabeledValue<NSString>.localizedString(forLabel: emaiadd.label!) 

        // let dic : [String : AnyObject] = [lable:emaiadd.value as String as AnyObject] 
        let dic : [String : AnyObject] = ["name":name2 as AnyObject, 
                 "type":lable as AnyObject, 
                 "typeof":"email" as AnyObject] 

        dataAll.add(dic) 


        if lable == "home" 
        { 

         if name2 == "" 
         { 

         } 
         else 
         { 
          email = emaiadd.value as String 


         } 

        } 
        if lable == "work" 
        { 
         if name2 == "" 
         { 

         } 
         else 
         { 
          workemail = emaiadd.value as String 

         } 

        } 
        if lable == "other" 
        { 
         if name2 == "" 
         { 

         } 
         else 
         { 
          otheremail = emaiadd.value as String 

         } 

        } 

       } 
      } 

     } 



     if (contact?.isKeyAvailable(CNContactPostalAddressesKey))! { 

      for addres:CNLabeledValue in (contact?.postalAddresses)! { 

       let addre = addres.value 
       let addre2 = addre.street 

       let lable :String = CNLabeledValue<NSString>.localizedString(forLabel: addres.label!) 


       let dic : [String : AnyObject] = ["name":addre2 as AnyObject, 
                "type":lable as AnyObject, 
                "typeof":"address" as AnyObject] 

       dataAll.add(dic) 

       if lable == "home" 
       { 
        if addre2 == "" 
        { 

        } 
        else 
        { 
         address = addre.street 



        } 
       } 

       if lable == "work" 
       { 
        if addre2 == "" 
        { 

        } 
        else 
        { 
         workaddress = addre.street 

        } 

       } 
       if lable == "other" 
       { 
        if addre2 == "" 
        { 

        } 
        else 
        { 
         otheraddress = addre.street 


        } 
       } 

       print(lable + (addre.street)) 
      } 


     } 

     if (contact?.isKeyAvailable(CNContactUrlAddressesKey))! { 

      for urladd:CNLabeledValue in (contact?.urlAddresses)! { 

       let url2 = (urladd.value as String) as String 

       let lable :String = CNLabeledValue<NSString>.localizedString(forLabel: urladd.label!) 


       let dic : [String : AnyObject] = ["name":url2 as AnyObject, 
                "type":lable as AnyObject, 
                "typeof":"url" as AnyObject] 

       dataAll.add(dic) 

       if lable == "home" 
       { 
        if url2 == "" 
        { 

        } 
        else 
        { 
         personalurl = urladd.value as String 



        } 
       } 
       if lable == "work" 
       { 
        if url2 == "" 
        { 

        } 
        else 
        { 
         companyurl = urladd.value as String 


        } 

       } 
       if lable == "other" 
       { 
        if url2 == "" 
        { 

        } 
        else 
        { 
         otherurl = urladd.value as String 



        } 

       } 


      } 

     } 

     if (contact?.isKeyAvailable(CNContactImageDataKey))! { 

      let image = contact?.imageData 

      let utf8str = image?.base64EncodedString() 


     } 



     dataArr = [["code": "Mobile", "title": othernumber],["code": "Work Number", "title": worknumber],["code": "OtherMobile", "title": number2],["code": "Email", "title": email],["code": "WorkEmail", "title": workemail],["code": "OtherEmail", "title": otheremail],["code": "Address", "title": address],["code": "Work Address", "title": workaddress],["code": "OtherAddress", "title": otheraddress],["code": "Company Name", "title": companyname],["code": "Designation", "title": jobtitle],["code": "Personal Website", "title": personalurl],["code": "Company Website", "title": companyurl],["code": "Other Website", "title": otherurl]] 
    } 

} 

接触からJSON内の複数のフィールドに

let contactPickerViewController = CNContactPickerViewController() 

     contactPickerViewController.delegate = self 

     present(contactPickerViewController, animated: true, completion: nil) 
+0

可能であればSwiftを扱うときは、Swiftのネイティブメソッド(NSMutableArray'など、 'Array 'を使用するなど)を持つデータ構造のFoundationバージョンを使用しないでください。また、不要な空白をすべて読み込むのは非常に難しいので、コードを再フォーマットする必要があります。実際のJSONオブジェクトではなく、辞書を返すだけなので、あなたの答えは実際には答えられません。質問にはCNContactPickerViewControllerという言葉はありませんでした。 –

関連する問題