how to retrive all CNContactStore from device without filter
Update
Based on comment from OP, please try the following CNContactFetchRequest-based API to retrieve all contacts without a filter. I run this on a background thread to reduce any possible issues huge numbers of contacts.
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)
})
})
}
Generally speaking you would normally set a predicate to nil to retrieve all of the contacts when using CNContactFetchRequest class rather than as described in your code.
Note
If you want to use your existing API then I recommend setting the predicate to true:
NSPredicate(value: true)
This should make all contacts return. If that does not work consider switching to the CNConctactFetchRequest API to enumerate the Contacts. In that event you could then set the predicate to nil to fetch all contacts (using CNConctactFetchRequest).
This is how you might modify the existing method:
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.")
}
})
}
})
}
And to use:
let contacts = findContacts()
Apple has a simpler sample:
let store = CNContactStore()
let contacts = try store.unifiedContactsMatchingPredicate(CNContact.predicateForContactsMatchingName("Appleseed"), keysToFetch:[CNContactGivenNameKey, CNContactFamilyNameKey])
For your use-case, you could try to modify the Apple Sample like this:
//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])
More Apple Samples for the Contacts Framework
Modified Tommie C's answer for 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()
}
}