Fetching all contacts in ios Swift?

后端 未结 7 1397
天命终不由人
天命终不由人 2020-11-30 20:00

I am aware of the ios swift has a Contacts Framework where I can fetch contacts, but I cannot find any method to fetch all the contacts together where I can access each of t

相关标签:
7条回答
  • 2020-11-30 20:12

    Please see my answer it is based on answers above with certain improvements, just do the following

    In your pod file

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

    then run pod install

    then in your ViewController File

    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")
        }
    }
    
    0 讨论(0)
  • 2020-11-30 20:13

    Swift 4 and 5. I have create class PhoneContacts. Please add NSContactsUsageDescription key to your info.plist file

     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
        }
    }
    

    The calling to above method in another class

    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.
    }
    

    Now, Get email and phone of contacts

        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 Model Class

    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()
        }
    }
    
    0 讨论(0)
  • 2020-11-30 20:21

    Many answers to Contact Framework questions suggest iterating over various containers (accounts). However, Apple's documentation describes a "Unified Contact" as

    Contacts in different accounts that represent the same person may be automatically linked together. Linked contacts are displayed in OS X and iOS apps as unified contacts. A unified contact is an in-memory, temporary view of the set of linked contacts that are merged into one contact.

    By default the Contacts framework returns unified contacts. Each fetched unified contact (CNContact) object has its own unique identifier that is different from any individual contact’s identifier in the set of linked contacts. A refetch of a unified contact should be done with its identifier. Source

    So simplest way to fetch a list of (partial, based on keys) contacts in a single array, would be the following:

        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")
        }
    
    0 讨论(0)
  • 2020-11-30 20:22

    A Swift 4.0 implementation to pull in all of the contacts.

    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)
    }
    

    This creates a local property to store the contacts, which are then populated via the enumeration against contactStore.

    0 讨论(0)
  • 2020-11-30 20:23

    Please Try below function, it helps you (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 讨论(0)
  • 2020-11-30 20:25
        // 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")
            }
        }
    
    0 讨论(0)
提交回复
热议问题