CNContact提取应该更快

时间:2017-09-25 10:06:59

标签: swift cncontact

我正在从CNContact获取联系人,花了.30秒来显示UI中的数千个联系人。我的客户希望我将时间缩短到0.01秒。他给了我Telegram app的例子。任何人都可以提供帮助

Ex Code:

typealias ContactsHandler =(_ contacts:[CNContact],_ error:NSError?) - >空隙

扩展名CDContactsPickerVC {

func getContacts(_ completion:  @escaping ContactsHandler) {
    if contactsStore == nil {
        //ContactStore is control for accessing the Contacts
        contactsStore = CNContactStore()
    }
    let error = NSError(domain: "CDContactPickerErrorDomain", code: 1, userInfo: [NSLocalizedDescriptionKey: "No Contacts Access"])

    switch CNContactStore.authorizationStatus(for: CNEntityType.contacts) {
    case CNAuthorizationStatus.denied, CNAuthorizationStatus.restricted:
        //User has denied the current app to access the contacts.

        let productName = Bundle.main.infoDictionary!["CFBundleName"]!

        let alert = UIAlertController(title: "Unable to access contacts", message: "\(productName) does not have access to contacts. Kindly enable it in privacy settings ", preferredStyle: UIAlertControllerStyle.alert)
        let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: {  action in
            completion([], error)
        })
        alert.addAction(okAction)
        self.present(alert, animated: true, completion: nil)

    case CNAuthorizationStatus.notDetermined:
        //This case means the user is prompted for the first time for allowing contacts
        contactsStore?.requestAccess(for: CNEntityType.contacts, completionHandler: { (granted, error) -> Void in
            //At this point an alert is provided to the user to provide access to contacts. This will get invoked if a user responds to the alert
            if  (!granted ){
                DispatchQueue.main.async(execute: { () -> Void in
                    completion([], error! as NSError?)
                })
            }
            else{
                self.getContacts(completion)
            }
        })

    case  CNAuthorizationStatus.authorized:
        //Authorization granted by user for this app.
        var contactsArray = [CNContact]()

        let contactFetchRequest = CNContactFetchRequest(keysToFetch: allowedContactKeys())

        do {
            try contactsStore?.enumerateContacts(with: contactFetchRequest, usingBlock: { (contact, stop) -> Void in
                //Ordering contacts based on alphabets in firstname
                contactsArray.append(contact)
                var key: String = "#"
                //If ordering has to be happening via family name change it here.
                if let firstLetter = contact.givenName[0..<1] , firstLetter.containsAlphabets() {
                    key = firstLetter.uppercased()
                }
                var contacts = [CNContact]()

                if let segregatedContact = self.orderedContacts[key] {
                    contacts = segregatedContact
                }


                var identifierArray = [String]()
                for contactDict in self.orderedContacts {
                    let contactArray = contactDict.value as [CNContact]
                    for cnObj in contactArray {
                        identifierArray.append(cnObj.identifier)
                    }
                }

                if identifierArray.contains(contact.identifier) {
                    // do nothing
                }else {
                    contacts.append(contact)
                    self.orderedContacts[key] = contacts
                }


            })
            self.sortedContactKeys = Array(self.orderedContacts.keys).sorted(by: <)
            if self.sortedContactKeys.first == "#" {
                self.sortedContactKeys.removeFirst()
                self.sortedContactKeys.append("#")
            }

            completion(contactsArray, nil)
        }
            //Catching exception as enumerateContactsWithFetchRequest can throw errors
        catch let error as NSError {
            print(error.localizedDescription)
        }

    }
}

func allowedContactKeys() -> [CNKeyDescriptor]{
    //We have to provide only the keys which we have to access. We should avoid unnecessary keys when fetching the contact. Reducing the keys means faster the access.
    return [CNContactNamePrefixKey as CNKeyDescriptor,
            CNContactGivenNameKey as CNKeyDescriptor,
            CNContactFamilyNameKey as CNKeyDescriptor,
            CNContactPhoneNumbersKey as CNKeyDescriptor,
            CNContactEmailAddressesKey as CNKeyDescriptor,
    ]
}

// MARK: - Contact Operations

open func reloadContacts() {
    DispatchQueue.global(qos: .background).async {
        self.getContacts( {(contacts, error) in
            if (error == nil) {
                DispatchQueue.main.async(execute: {
                    self.emptyContactLabel.isHidden = contacts.count > 0 ? true : false
                    self.tableView.reloadData()
                })
                self.updateContactsInLocalDB(contacts: contacts)
            }
        })
    }
}

0 个答案:

没有答案