Ios 如何从没有筛选器的设备检索所有CNContactStore
我正在尝试插入Ios 如何从没有筛选器的设备检索所有CNContactStore,ios,swift,cncontact,Ios,Swift,Cncontact,我正在尝试插入var联系人:[CNContact]=[] var store=CNContactStore()但是我没有找到这个作业的正确代码,我找到了这个函数,我需要给它一个名称 func findContactsWithName(name: String) { AppDelegate.sharedDelegate().checkAccessStatus({ (accessGranted) -> Void in if accessGranted {
var联系人:[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.")
}
})
}
})
}
我想插入所有的记录,而不仅仅是一个名字相等的记录,更新 根据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)
})
})
}
一般来说,在使用类时,您通常会将谓词设置为nil以检索所有联系人,而不是像代码中所描述的那样
注意
如果要使用现有API,我建议将谓词设置为true:
NSPredicate(value: true)
这将使所有联系人返回。如果这不起作用,考虑切换到CNCtTractFutChestAPI API来枚举联系人。在这种情况下,您可以将谓词设置为nil以获取所有联系人(使用cnconctfetchrequest)
以下是修改现有方法的方式:
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.")
}
})
}
})
}
以及使用:
let contacts = findContacts()
苹果有一个更简单的例子:
let store = CNContactStore()
let contacts = try store.unifiedContactsMatchingPredicate(CNContact.predicateForContactsMatchingName("Appleseed"), keysToFetch:[CNContactGivenNameKey, CNContactFamilyNameKey])
对于您的用例,您可以尝试这样修改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])
修改了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()
}
}
///要获取的默认密钥描述符
public var defaultFetchKeys:[String]=[CNContactGivenNameKey,
CNContactFamilyNameKey,
CNContactPhoneNumbersKey,
CNContactImageDataAvailableKey,
CNContactThumbnailImageDataKey]
/**
从用户的设备获取联系人
-参数sortOrder:应使用的排序顺序。默认无。
-返回:联系人列表
*/
public func fetchContacts(带有排序顺序:CNContactSortOrder=.givenName,
qos:DispatchQoS.QoSClass=.background)->Promise
{
返回承诺{盖章
DispatchQueue.global(qos:qos).async{
let store=CNContactStore()
变量触点=[触点]()
///用于解析和格式化数字的`PhoneNumberKit`对象(昂贵!)
设phoneNumberKit=phoneNumberKit()
let request=CNContactFetchRequest(keystefetch:self.defaultFetchKeys作为[CNKeyDescriptor])
request.sortOrder=sortOrder
request.unifyResults=true
做{
尝试存储。枚举联系人(with:request){contact,u
如果let user=Contact(Contact:Contact,kit:phoneNumberKit){
contacts.append(用户)
}
}
DispatchQueue.main.async{
密封(触点)
}
}抓住{
DispatchQueue.main.async{
密封。拒绝(错误)
}
}
}
}
}
我也在使用
PhoneNumberKit
来标准化所有数字,并PromiseKit
来链接我的请求,但你几乎可以根据需要进行调整。由于未捕获的异常“CNInvalidPredicateException”,我正在终止应用程序,原因:“谓词TRUEPREDICATE不是有效的联系人predicat@shaharnakash-请参阅提供的CNContactFetchRequest示例。请让我知道这在您的情况下是否有效?C现在可以了,我按照您的建议使用let fetchRequest=CNContactFetchRequest(keystefetch:keystefetch),现在一切都很完美:)嘿,Tommie!我刚刚用我的朋友iPhone运行了这段代码,我们只获得了整个联系人的10%。你知道这是什么原因吗?或者,无论来源如何,我们如何才能收到完整的联系人列表?@RoiMulia-我不确定您何时何地调用此代码,但请注意,在窗口事件等位置调用后台线程可能会导致Apple框架使用的竞争线程出现问题。我会尝试从viewDidLoad或在某些操作上调用代码,但请记住线程可能会导致争用条件。另外,请确保使用统一联系人设置。。。也可能是其他的事情,没有更多的背景我就说不出来。如果这些建议对您有帮助,请告诉我。您好,下面的代码行将给出您的姓名、姓氏、生日。**如果要检索联系人的所有详细信息,请使用keystefetch=[CNContactGivenNameKey、CNContactFamilyNameKey、CNContactBirthdayKey、CNContactViewController.descriptorForRequiredKeys()]**如何获取?。
/// The default key descriptors to fetch
public var defaultFetchKeys: [String] = [CNContactGivenNameKey,
CNContactFamilyNameKey,
CNContactPhoneNumbersKey,
CNContactImageDataAvailableKey,
CNContactThumbnailImageDataKey]
/**
Fetch contacts from the user's device
- parameter sortOrder: The sort order that should be used. Default none.
- returns: A list of contacts
*/
public func fetchContacts(withSortOrder sortOrder: CNContactSortOrder = .givenName,
qos: DispatchQoS.QoSClass = .background) -> Promise<[Contact]>
{
return Promise { seal in
DispatchQueue.global(qos: qos).async {
let store = CNContactStore()
var contacts = [Contact]()
/// A `PhoneNumberKit` object used to parse and format numbers (expensive!)
let phoneNumberKit = PhoneNumberKit()
let request = CNContactFetchRequest(keysToFetch: self.defaultFetchKeys as [CNKeyDescriptor])
request.sortOrder = sortOrder
request.unifyResults = true
do {
try store.enumerateContacts(with: request) { contact, _ in
if let user = Contact(contact: contact, kit: phoneNumberKit) {
contacts.append(user)
}
}
DispatchQueue.main.async {
seal.fulfill(contacts)
}
} catch {
DispatchQueue.main.async {
seal.reject(error)
}
}
}
}
}