How to fetch all contacts record in iOS 9 using Contacts Framework

前端 未结 20 1522
[愿得一人]
[愿得一人] 2020-11-28 01:52

Most part of AddressBook framework is deprecated in iOS 9. In the new Contacts Framework documentation only shows how to fetch records matches a NSPredicate, bu

相关标签:
20条回答
  • 2020-11-28 02:02

    Apple actually recommends enumerateContactsWithFetchRequest of CNContactStore to fetch all contacts and NOT unifiedContactsMatchingPredicate.

    Below is the working code for Obj-C.

    CNContactStore *store = [[CNContactStore alloc] init];
    
    //keys with fetching properties
    NSArray *keys = @[CNContactGivenNameKey, CNContactPhoneNumbersKey]; 
    CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
    NSError *error;
    
    [store enumerateContactsWithFetchRequest:request error:&error usingBlock:^(CNContact * __nonnull contact, BOOL * __nonnull stop) {
    
            // access it this way -> contact.givenName; etc
    
    }];
    

    Here is the link where apple recommends enumerate function: https://developer.apple.com/reference/contacts/cncontactstore/1403266-unifiedcontactsmatchingpredicate?language=objc#discussion

    If link expired, here is what Apple wrote:

    If no matches are found, this method returns an empty array (or nil in case of error). Use only the predicates from the CNContact class predicates. Compound predicates are not supported by this method. Due to unification, the returned contacts may have different identifiers than you specify. To fetch all contacts, use enumerateContactsWithFetchRequest:error:usingBlock:.

    0 讨论(0)
  • 2020-11-28 02:02

    I am trying this code it works fine. I can fetch all contacts details using this code in swift3 latest framework using contacts:

    let requestForContacts = CNContactFetchRequest(keysToFetch: [CNContactIdentifierKey as CNKeyDescriptor, CNContactFormatter.descriptorForRequiredKeys(for: CNContactFormatterStyle.fullName), CNContactPhoneNumbersKey as CNKeyDescriptor ,CNContactImageDataKey as CNKeyDescriptor,CNContactEmailAddressesKey as CNKeyDescriptor,CNContactBirthdayKey as CNKeyDescriptor])
    do {
        try self.store.enumerateContacts(with: requestForContacts) { contact, stop in
            print("contact:\(contact)")
            self.contacts.append(contact)
        }
    } catch {
        print(error)
    }
    
    for contact in self.contacts {
        print(contact)
        let firstName = contact.givenName
        nameArray.append(firstName)
        print("first:\(firstName)")
        let phoneNumber = (contact.phoneNumbers[0].value).value(forKey: "digits")
        phoneNumberArray.append(phoneNumber as! String)
        let emailAddress = contact.emailAddresses[0].value(forKey: "value")
        emailAddressArray.append(emailAddress as! String)
    }
    
    0 讨论(0)
  • 2020-11-28 02:07

    Both other answers do only load contacts from the container with the defaultContainerIdentifier. In a scenario, where the user has more than one container (i.e. an Exchange and an iCloud account which both are used to store contacts), this would only load the contacts from the account that is configured as the default. Therefore, it would not load all contacts as requested by the author of the question.

    What you'll probably want to do instead is getting all the containers and iterate over them to extract all contacts from each of them. The following code snippet is an example of how we do it in one of our apps (in Swift):

    lazy var contacts: [CNContact] = {
        let contactStore = CNContactStore()
        let keysToFetch = [
            CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName),
            CNContactEmailAddressesKey,
            CNContactPhoneNumbersKey,
            CNContactImageDataAvailableKey,
            CNContactThumbnailImageDataKey]
    
        // Get all the containers
        var allContainers: [CNContainer] = []
        do {
            allContainers = try contactStore.containersMatchingPredicate(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.predicateForContactsInContainerWithIdentifier(container.identifier)
    
            do {
                let containerResults = try contactStore.unifiedContactsMatchingPredicate(fetchPredicate, keysToFetch: keysToFetch)
                results.appendContentsOf(containerResults)
            } catch {
                print("Error fetching results for container")
            }
        }
    
        return results
    }()
    
    0 讨论(0)
  • 2020-11-28 02:08

    For Swift 4

            var results: [CNContact] = []
    
            let fetchRequest = CNContactFetchRequest(keysToFetch: [CNContactGivenNameKey as CNKeyDescriptor, CNContactFamilyNameKey as CNKeyDescriptor, CNContactMiddleNameKey as CNKeyDescriptor, CNContactEmailAddressesKey as CNKeyDescriptor,CNContactPhoneNumbersKey as CNKeyDescriptor])
    
            fetchRequest.sortOrder = CNContactSortOrder.userDefault
    
            let store = CNContactStore()
    
            do {
                try store.enumerateContacts(with: fetchRequest, usingBlock: { (contact, stop) -> Void in
                    print(contact.phoneNumbers.first?.value ?? "no")
                    results.append(contact)
    
                })
            }
            catch let error as NSError {
                print(error.localizedDescription)
            }
    

    Older version for swift var results contains all contact

    let contactStore = CNContactStore()
        var results: [CNContact] = []
        do {
            try contactStore.enumerateContactsWithFetchRequest(CNContactFetchRequest(keysToFetch: [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactMiddleNameKey, CNContactEmailAddressesKey,CNContactPhoneNumbersKey])) {
                (contact, cursor) -> Void in
                results.append(contact)
                }
        }
        catch{
            print("Handle the error please")
        }
    
    0 讨论(0)
  • 2020-11-28 02:11

    Cody's response in Swift 3:

    import Contacts
    

    Then within whatever function you're using:

               let store = CNContactStore()
                store.requestAccess(for: .contacts, completionHandler: {
                    granted, error in
    
                    guard granted else {
                        let alert = UIAlertController(title: "Can't access contact", message: "Please go to Settings -> MyApp to enable contact permission", preferredStyle: .alert)
                        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
                        self.present(alert, animated: true, completion: nil)
                        return
                    }
    
                    let keysToFetch = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName), CNContactPhoneNumbersKey] as [Any]
                    let request = CNContactFetchRequest(keysToFetch: keysToFetch as! [CNKeyDescriptor])
                    var cnContacts = [CNContact]()
    
                    do {
                        try store.enumerateContacts(with: request){
                            (contact, cursor) -> Void in
                            cnContacts.append(contact)
                        }
                    } catch let error {
                        NSLog("Fetch contact error: \(error)")
                    }
    
                    print(">>>> Contact list:")
                    for contact in cnContacts {
                        let fullName = CNContactFormatter.string(from: contact, style: .fullName) ?? "No Name"
                        print("\(fullName): \(contact.phoneNumbers.description)")
                    }
                })
    
    0 讨论(0)
  • 2020-11-28 02:12

    In swift 3 and Xcode 8 you can get all contacts list

    let keys = [CNContactGivenNameKey ,CNContactImageDataKey,CNContactPhoneNumbersKey]
            var message: String!
            //let request=CNContactFetchRequest(keysToFetch: keys)
            let contactsStore = AppDelegate.AppDel.contactStore
            // Get all the containers
            var allContainers: [CNContainer] = []
            do {
                allContainers = try contactsStore.containers(matching: nil)
            } catch {
                print("Error fetching containers")
            }
    
    
    
            // 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 contactsStore.unifiedContacts(matching: fetchPredicate, keysToFetch: keys as [CNKeyDescriptor])
                    self.results.append(contentsOf: containerResults)
                    self.tableView.reloadData()
                    message="\(self.results.count)"
                } catch {
                    print("Error fetching results for container")
                }
            }
    
    0 讨论(0)
提交回复
热议问题