web-dev-qa-db-ja.com

iOS Swiftですべての連絡先を取得しますか?

Ios Swiftには Contacts Framework があり、連絡先を取得できますが、それぞれにアクセスできるすべての連絡先を一緒に取得する方法が見つかりません連絡先を取得するためのすべてのメソッドには、何らかの条件が必要なようですが、すべての連絡先をまとめることができる方法はありますか?

ありがとう

33
the_naive

Contact Frameworkの質問に対する多くの回答は、さまざまなコンテナ(アカウント)を反復処理することを示唆しています。ただし、Appleのドキュメントでは、「Unified Contact」について次のように説明しています。

同じ人物を表す異なるアカウントの連絡先は、自動的にリンクされる場合があります。リンクされた連絡先は、OS XおよびiOSアプリで統合連絡先として表示されます。統合連絡先は、1つの連絡先にマージされるリンクされた連絡先のセットのメモリ内の一時的なビューです。

デフォルトでは、Contactsフレームワークは統合された連絡先を返します。フェッチされた各統合連絡先(CNContact)オブジェクトには、リンクされた連絡先セット内の個々の連絡先の識別子とは異なる独自の一意の識別子があります。統合された連絡先の再取得は、その識別子を使用して行う必要があります。 ソース

単一の配列で(キーに基づいて部分的に)連絡先のリストを取得する最も簡単な方法は、次のとおりです。

    var contacts = [CNContact]()
    let keys = [CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName)]
    let request = CNContactFetchRequest(keysToFetch: keys)

    do {
        try self.contactStore.enumerateContactsWithFetchRequest(request) {             
            (contact, stop) in
            // Array containing all unified contacts from everywhere
            contacts.append(contact)
        }
    } 
    catch {
        print("unable to fetch contacts")
    }
24
Ri_

Swift 4および5。クラスPhoneContactsを作成しました。 NSContactsUsageDescriptionキーをinfo.plistファイルに追加してください

 import Foundation
 import ContactsUI

class PhoneContacts {

    class func getContacts(filter: ContactsFilter = .none) -> [CNContact] { //  ContactsFilter is Enum find it below

        let contactStore = CNContactStore()
        let keysToFetch = [
            CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
            CNContactPhoneNumbersKey,
            CNContactEmailAddressesKey,
            CNContactThumbnailImageDataKey] as [Any]

        var allContainers: [CNContainer] = []
        do {
            allContainers = try contactStore.containers(matching: nil)
        } catch {
            print("Error fetching containers")
        }

        var results: [CNContact] = []

        for container in allContainers {
            let fetchPredicate = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)

            do {
                let containerResults = try contactStore.unifiedContacts(matching: fetchPredicate, keysToFetch: keysToFetch as! [CNKeyDescriptor])
                results.append(contentsOf: containerResults)
            } catch {
                print("Error fetching containers")
            }
        }
        return results
    }
}

別のクラスで上記のメソッドを呼び出す

import ContactsUI
func phoneNumberWithContryCode() -> [String] {

    let contacts = PhoneContacts.getContacts() // here calling the getContacts methods
    var arrPhoneNumbers = [String]()
    for contact in contacts {
        for ContctNumVar: CNLabeledValue in contact.phoneNumbers {
            if let fulMobNumVar  = ContctNumVar.value as? CNPhoneNumber {
                //let countryCode = fulMobNumVar.value(forKey: "countryCode") get country code
                   if let MccNamVar = fulMobNumVar.value(forKey: "digits") as? String {
                        arrPhoneNumbers.append(MccNamVar)
                }
            }
        }
    }
    return arrPhoneNumbers // here array has all contact numbers.
}

今、連絡先の電子メールと電話を取得

    enum ContactsFilter {
        case none
        case mail
        case message
    }

    var phoneContacts = [PhoneContact]() // array of PhoneContact(It is model find it below) 
    var filter: ContactsFilter = .none

    self.loadContacts(filter: filter) // Calling loadContacts methods

       fileprivate func loadContacts(filter: ContactsFilter) {
            phoneContacts.removeAll()
            var allContacts = [PhoneContact]()
            for contact in PhoneContacts.getContacts(filter: filter) {
                allContacts.append(PhoneContact(contact: contact))
            }

            var filterdArray = [PhoneContact]()
            if self.filter == .mail {
                filterdArray = allContacts.filter({ $0.email.count > 0 }) // getting all email 
            } else if self.filter == .message {
                filterdArray = allContacts.filter({ $0.phoneNumber.count > 0 })
            } else {
                filterdArray = allContacts
            }
            phoneContacts.append(contentsOf: filterdArray)

  for contact in phoneContacts {
      print("Name -> \(contact.name)")
      print("Email -> \(contact.email)")
      print("Phone Number -> \(contact.phoneNumber)")
    }
    let arrayCode  = self.phoneNumberWithContryCode()
    for codes in arrayCode {
      print(codes)
    }
     DispatchQueue.main.async {
       self.tableView.reloadData() // update your tableView having phoneContacts array
              }
            }
        }

PhoneContactモデルクラス

import Foundation
import ContactsUI

class PhoneContact: NSObject {

    var name: String?
    var avatarData: Data?
    var phoneNumber: [String] = [String]()
    var email: [String] = [String]()
    var isSelected: Bool = false
    var isInvited = false

    init(contact: CNContact) {
        name        = contact.givenName + " " + contact.familyName
        avatarData  = contact.thumbnailImageData
        for phone in contact.phoneNumbers {
            phoneNumber.append(phone.value.stringValue)
        }
        for mail in contact.emailAddresses {
            email.append(mail.value as String)
        }
    }

    override init() {
        super.init()
    }
}
18
GSK

Swift 4の更新

let contactStore = CNContactStore()
var contacts = [CNContact]()
let keys = [
        CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
                CNContactPhoneNumbersKey,
                CNContactEmailAddressesKey
        ] as [Any]
let request = CNContactFetchRequest(keysToFetch: keys as! [CNKeyDescriptor])
do {
    try contactStore.enumerateContacts(with: request){
            (contact, stop) in
        // Array containing all unified contacts from everywhere
        contacts.append(contact)
        for phoneNumber in contact.phoneNumbers {
            if let number = phoneNumber.value as? CNPhoneNumber, let label = phoneNumber.label {
                let localizedLabel = CNLabeledValue<CNPhoneNumber>.localizedString(forLabel: label)
                print("\(contact.givenName) \(contact.familyName) tel:\(localizedLabel) -- \(number.stringValue), email: \(contact.emailAddresses)")
            }
        }
    }
    print(contacts)
} catch {
    print("unable to fetch contacts")
}
15
Shan Ye
    // You may add more "keys" to fetch referred to official documentation
    let keysToFetch = [CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName)]

    // The container means 
    // that the source the contacts from, such as Exchange and iCloud
    var allContainers: [CNContainer] = []
    do {
        allContainers = try store.containersMatchingPredicate(nil)
    } catch {
        print("Error fetching containers")
    }

    var contacts: [CNContact] = []

    // Loop the containers
    for container in allContainers {
        let fetchPredicate = CNContact.predicateForContactsInContainerWithIdentifier(container.identifier)

        do {
            let containerResults = try store.unifiedContactsMatchingPredicate(fetchPredicate, keysToFetch: keysToFetch)
            // Put them into "contacts"
            contacts.appendContentsOf(containerResults)
        } catch {
            print("Error fetching results for container")
        }
    }
6
Christopher

すべての連絡先を取り込むためのSwift 4.0の実装。

let contactStore = CNContactStore()
var contacts = [CNContact]()
let keys = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName)]
let request = CNContactFetchRequest(keysToFetch: keys)

do {
    try contactStore.enumerateContacts(with: request) { (contact, stop) in
        contacts.append(contact)
    }
} catch {
    print(error.localizedDescription)
}

これにより、連絡先を保存するローカルプロパティが作成され、contactStoreに対する列挙を介して入力されます。

5
CodeBender

上記の回答に基づいて特定の改善を加えた私の回答をご覧ください。

ポッドファイル内

source 'https://github.com/CocoaPods/Specs.git'
pod 'PhoneNumberKit', '~> 2.6'

ポッドインストールを実行

その後、ViewControllerファイルで

import Contacts
import PhoneNumberKit
import UIKit

override func viewDidLoad() {
    super.viewDidLoad()

    let contactStore = CNContactStore()
    var contacts = [CNContact]()
    let keys = [
        CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
        CNContactPhoneNumbersKey,
        CNContactEmailAddressesKey,
    ] as [Any]
    let request = CNContactFetchRequest(keysToFetch: keys as! [CNKeyDescriptor])
    do {
        try contactStore.enumerateContacts(with: request) {
            contact, _ in
            // Array containing all unified contacts from everywhere
            contacts.append(contact)
            for phoneNumber in contact.phoneNumbers {
                if let number = phoneNumber.value as? CNPhoneNumber, let label = phoneNumber.label {
                    let localizedLabel = CNLabeledValue<CNPhoneNumber>.localizedString(forLabel: label)

                    // Get The Name
                    let name = contact.givenName + " " + contact.familyName
                    print(name)

                    // Get The Mobile Number
                    var mobile = number.stringValue
                    mobile = mobile.replacingOccurrences(of: " ", with: "")

                    // Parse The Mobile Number
                    let phoneNumberKit = PhoneNumberKit()

                    do {
                        let phoneNumberCustomDefaultRegion = try phoneNumberKit.parse(mobile, withRegion: "IN", ignoreType: true)
                        let countryCode = String(phoneNumberCustomDefaultRegion.countryCode)
                        let mobile = String(phoneNumberCustomDefaultRegion.nationalNumber)
                        let finalMobile = "+" + countryCode + mobile
                        print(finalMobile)
                    } catch {
                        print("Generic parser error")
                    }

                    // Get The Email
                    var email: String
                    for mail in contact.emailAddresses {
                        email = mail.value as String
                        print(email)
                    }
                }
            }
        }

    } catch {
        print("unable to fetch contacts")
    }
}
2
DragonFire

以下の機能を試してください、それはあなたを助けます(Swift 4)

import UIKit
import Contacts
import ContactsUI

override func viewDidLoad() {
    super.viewDidLoad()

    // `contacts` Contains all details of Phone Contacts
    let contacts = self.getContactFromCNContact() 
    for contact in contacts {

        print(contact.middleName)
        print(contact.familyName)
        print(contact.givenName)
    }
}

func getContactFromCNContact() -> [CNContact] {

    let contactStore = CNContactStore()
    let keysToFetch = [
        CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
        CNContactGivenNameKey,
        CNContactMiddleNameKey,
        CNContactFamilyNameKey,
        CNContactEmailAddressesKey,
        ] as [Any]

    //Get all the containers
    var allContainers: [CNContainer] = []
    do {
        allContainers = try contactStore.containers(matching: nil)
    } catch {
        print("Error fetching containers")
    }

    var results: [CNContact] = []

    // Iterate all containers and append their contacts to our results array
    for container in allContainers {

        let fetchPredicate = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)

        do {
            let containerResults = try contactStore.unifiedContacts(matching: fetchPredicate, keysToFetch: keysToFetch as! [CNKeyDescriptor])
            results.append(contentsOf: containerResults)

        } catch {
            print("Error fetching results for container")
        }
    }

    return results
}
0
Rohit Makwana