如何从没有过滤器的设备中检索所有CNContactStore

sha*_*ash 7 ios swift cncontact

我想插入var contacts: [CNContact] = []var store = CNContactStore(),但我没有找到合适的代码这份工作,我发现这个功能,我需要给一个名字

func findContactsWithName(name: String) {
    AppDelegate.sharedDelegate().checkAccessStatus({ (accessGranted) -> Void in
        if accessGranted {
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                do {
                    let predicate: NSPredicate = CNContact.predicateForContactsMatchingName(name)
                    let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactBirthdayKey, CNContactViewController.descriptorForRequiredKeys()]
                    self.contacts = try self.store.unifiedContactsMatchingPredicate(predicate, keysToFetch:keysToFetch)


                    self.tableView.reloadData()
                }
                catch {
                    print("Unable to refetch the selected contact.")
                }
            })
        }
    })
}
Run Code Online (Sandbox Code Playgroud)

我想插入self.contacts所有记录,而不只是一个名称相等的记录

Tom*_* C. 9

更新

根据OP的评论,请尝试以下基于CNContactFetchRequest的API来检索没有过滤器的所有联系人.我在后台线程上运行它来减少任何可能的问题大量的联系人.

func findContactsOnBackgroundThread ( completionHandler:(contacts:[CNContact]?)->()) {

        dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), { () -> Void in

            let keysToFetch = [CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName),CNContactPhoneNumbersKey] //CNContactIdentifierKey
            let fetchRequest = CNContactFetchRequest( keysToFetch: keysToFetch)
            var contacts = [CNContact]()
            CNContact.localizedStringForKey(CNLabelPhoneNumberiPhone)

            fetchRequest.mutableObjects = false
            fetchRequest.unifyResults = true
            fetchRequest.sortOrder = .UserDefault

            let contactStoreID = CNContactStore().defaultContainerIdentifier()
            print("\(contactStoreID)")


            do {

                try CNContactStore().enumerateContactsWithFetchRequest(fetchRequest) { (contact, stop) -> Void in
                    //do something with contact
                    if contact.phoneNumbers.count > 0 {
                        contacts.append(contact)
                    }

                }
            } catch let e as NSError {
                print(e.localizedDescription)
            }

            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                completionHandler(contacts: contacts)

            })
        })
    }
Run Code Online (Sandbox Code Playgroud)

一般来说,在使用CNContactFetchRequest类而不是代码中描述的时候,通常会将谓词设置为nil以检索所有联系人.

注意

如果您想使用现有的API,我建议将谓词设置为true:

 NSPredicate(value: true)
Run Code Online (Sandbox Code Playgroud)

这应该使所有联系人都返回.如果这不起作用,请考虑切换到CNConctactFetchRequest API以枚举联系人.在那种情况下,您可以将谓词设置为nil以获取所有联系人(使用CNConctactFetchRequest).

CNContactFetch谓语

这是您可以修改现有方法的方法:

func findContacts()->[CNContact] {
        AppDelegate.sharedDelegate().checkAccessStatus({ (accessGranted) -> Void in
            if accessGranted {
                dispatch_async(dispatch_get_main_queue(), { () -> Void in
                    do {
                        let predicate: NSPredicate = NSPredicate(value: true)
                        let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactBirthdayKey, CNContactViewController.descriptorForRequiredKeys()]
                        self.contacts = try self.store.unifiedContactsMatchingPredicate(predicate, keysToFetch:keysToFetch)


                        self.tableView.reloadData()
                    }
                    catch {
                        print("Unable to refetch the selected contact.")
                    }
                })
            }
        })
    }
Run Code Online (Sandbox Code Playgroud)

并使用:

let contacts = findContacts()
Run Code Online (Sandbox Code Playgroud)

Apple有一个更简单的样本:

let store = CNContactStore()
let contacts = try store.unifiedContactsMatchingPredicate(CNContact.predicateForContactsMatchingName("Appleseed"), keysToFetch:[CNContactGivenNameKey, CNContactFamilyNameKey])
Run Code Online (Sandbox Code Playgroud)

对于您的用例,您可以尝试像这样修改Apple示例:

//Use the reference to look up additional keys constants that you may want to fetch
let store = CNContactStore()
let contacts = try store.unifiedContactsMatchingPredicate(NSPredicate(value: true), keysToFetch:[CNContactGivenNameKey, CNContactFamilyNameKey])
Run Code Online (Sandbox Code Playgroud)

联系人框架的更多Apple示例

  • 由于未捕获的异常'CNInvalidPredicateException',我正在试图终止应用程序,原因:'谓词TRUEPREDICATE不是有效的联系人谓词 (2认同)

小智 9

修改了Tommie C对XCode 8和Swift 3.0的回答.

func findContactsOnBackgroundThread ( completionHandler:@escaping (_ contacts:[CNContact]?)->()) {

    DispatchQueue.global(qos: .userInitiated).async(execute: { () -> Void in

        let keysToFetch = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName),CNContactPhoneNumbersKey] as [Any] //CNContactIdentifierKey
        let fetchRequest = CNContactFetchRequest( keysToFetch: keysToFetch as! [CNKeyDescriptor])
        var contacts = [CNContact]()
        CNContact.localizedString(forKey: CNLabelPhoneNumberiPhone)

        if #available(iOS 10.0, *) {
            fetchRequest.mutableObjects = false
        } else {
            // Fallback on earlier versions
        }
        fetchRequest.unifyResults = true
        fetchRequest.sortOrder = .userDefault

        let contactStoreID = CNContactStore().defaultContainerIdentifier()
        print("\(contactStoreID)")


        do {

            try CNContactStore().enumerateContacts(with: fetchRequest) { (contact, stop) -> Void in
                //do something with contact
                if contact.phoneNumbers.count > 0 {
                    contacts.append(contact)
                }

            }
        } catch let e as NSError {
            print(e.localizedDescription)
        }

        DispatchQueue.main.async(execute: { () -> Void in
            completionHandler(contacts)

        })
    })
} 

override func viewDidLoad() {
    findContactsOnBackgroundThread { (contacts) in
            self.contactsList = contacts
            self.tableView.reloadData()
        }
}
Run Code Online (Sandbox Code Playgroud)