如何使用联系人框架获取iOS 9中的所有联系人logging

在iOS 9中不推荐使用地址簿框架的大部分内容。在新的“联系人框架” 文档中,仅显示如何获取与NSPredicate相匹配的NSPredicate ,但是如果我需要所有logging呢?

两个其他的答案只能使用defaultContainerIdentifier从容器中加载联系人。 在用户有多个容器的情况下(即Exchange和iCloud帐户都用于存储联系人),这只会从configuration为默认帐户的帐户加载联系人。 因此,它不会按照问题作者的要求加载所有联系人。

你可能想要做的是取得所有的容器,并遍历它们从每个容器中提取所有的联系人。 下面的代码片段是我们如何在我们的一个应用程序(在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 }() 

Objective-C的:

 //ios 9+ CNContactStore *store = [[CNContactStore alloc] init]; [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted == YES) { //keys with fetching properties NSArray *keys = @[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey]; NSString *containerId = store.defaultContainerIdentifier; NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId]; NSError *error; NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error]; if (error) { NSLog(@"error fetching contacts %@", error); } else { for (CNContact *contact in cnContacts) { // copy data to my custom Contacts class. Contact *newContact = [[Contact alloc] init]; newContact.firstName = contact.givenName; newContact.lastName = contact.familyName; UIImage *image = [UIImage imageWithData:contact.imageData]; newContact.image = image; for (CNLabeledValue *label in contact.phoneNumbers) { NSString *phone = [label.value stringValue]; if ([phone length] > 0) { [contact.phones addObject:phone]; } } } } } }]; 

也要获取所有联系人,您可以使用enumerateContactsWithFetchRequest方法:

 CNContactStore *store = [[CNContactStore alloc] init]; [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted == YES) { //keys with fetching properties NSArray *keys = @[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey]; CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys]; NSError *error; BOOL success = [store enumerateContactsWithFetchRequest:request error:&error usingBlock:^(CNContact * __nonnull contact, BOOL * __nonnull stop) { if (error) { NSLog(@"error fetching contacts %@", error); } else { // copy data to my custom Contact class. Contact *newContact = [[Contact alloc] init]; newContact.firstName = contact.givenName; newContact.lastName = contact.familyName; // etc. } }]; } }]; 

如果你想通过名字过滤联系人,你可以使用这个:

OBJ-C:

 // keys from example above NSArray *keys = @[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey]; NSArray *cnContacts = [store unifiedContactsMatchingPredicate:[CNContact predicateForContactsMatchingName:@"John Appleseed"] keysToFetch:keys error:&error]; 

Swift 3:

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

官方文档在这里: https : //developer.apple.com/reference/contacts

使用Swift联系人框架来获取所有联系人,包括姓名和电话号码

 import contacts let store = CNContactStore() store.requestAccessForEntityType(.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.presentViewController(alert, animated: true, completion: nil) return } let keysToFetch = [CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName), CNContactPhoneNumbersKey] let request = CNContactFetchRequest(keysToFetch: keysToFetch) var cnContacts = [CNContact]() do { try store.enumerateContactsWithFetchRequest(request){ (contact, cursor) -> Void in cnContacts.append(contact) } } catch let error { NSLog("Fetch contact error: \(error)") } NSLog(">>>> Contact list:") for contact in cnContacts { let fullName = CNContactFormatter.stringFromContact(contact, style: .FullName) ?? "No Name" NSLog("\(fullName): \(contact.phoneNumbers.description)") } }) 

获取联系人是操作,所以你不应该阻止主UI线程。 在后台线程上执行CNContactFetchRequest 。 这就是为什么我把代码放到completionHandler中。 它在后台线程上运行。

实际上,Applebuild议使用CNContactStore的enumerateContactsWithFetchRequest来获取所有联系人,而不是 unifiedContactsMatchingPredicate。

以下是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 }]; 

这里是苹果推荐枚举函数的链接: https : //developer.apple.com/reference/contacts/cncontactstore/1403266-unifiedcontactsmatchingpredicate?language=objc#discussion

如果链接过期,苹果公司写道:

如果找不到匹配项,则此方法返回一个空数组(如果有错误,则返回nil)。 仅使用来自CNContact类谓词的谓词。 这个方法不支持复合谓词。 由于统一,返回的联系人可能具有不同于您指定的标识符。 要获取所有联系人 ,请使用enumerateContactsWithFetchRequest:error:usingBlock:

从iOS9的联系人框架中获取全名,电子邮件地址,电话号码,个人资料图片和生日

 #pragma mark #pragma mark -- Getting Contacts From AddressBook -(void)contactsDetailsFromAddressBook{ //ios 9+ CNContactStore *store = [[CNContactStore alloc] init]; [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted == YES) { //keys with fetching properties NSArray *keys = @[CNContactBirthdayKey,CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey, CNContactEmailAddressesKey]; NSString *containerId = store.defaultContainerIdentifier; NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId]; NSError *error; NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error]; if (error) { NSLog(@"error fetching contacts %@", error); } else { NSString *phone; NSString *fullName; NSString *firstName; NSString *lastName; UIImage *profileImage; NSDateComponents *birthDayComponent; NSMutableArray *contactNumbersArray; NSString *birthDayStr; NSMutableArray *emailArray; NSString* email = @""; for (CNContact *contact in cnContacts) { // copy data to my custom Contacts class. firstName = contact.givenName; lastName = contact.familyName; birthDayComponent = contact.birthday; if (birthDayComponent == nil) { // NSLog(@"Component: %@",birthDayComponent); birthDayStr = @"DOB not available"; }else{ birthDayComponent = contact.birthday; NSInteger day = [birthDayComponent day]; NSInteger month = [birthDayComponent month]; NSInteger year = [birthDayComponent year]; // NSLog(@"Year: %ld, Month: %ld, Day: %ld",(long)year,(long)month,(long)day); birthDayStr = [NSString stringWithFormat:@"%ld/%ld/%ld",(long)day,(long)month,(long)year]; } if (lastName == nil) { fullName=[NSString stringWithFormat:@"%@",firstName]; }else if (firstName == nil){ fullName=[NSString stringWithFormat:@"%@",lastName]; } else{ fullName=[NSString stringWithFormat:@"%@ %@",firstName,lastName]; } UIImage *image = [UIImage imageWithData:contact.imageData]; if (image != nil) { profileImage = image; }else{ profileImage = [UIImage imageNamed:@"placeholder.png"]; } for (CNLabeledValue *label in contact.phoneNumbers) { phone = [label.value stringValue]; if ([phone length] > 0) { [contactNumbersArray addObject:phone]; } } ////Get all E-Mail addresses from contacts for (CNLabeledValue *label in contact.emailAddresses) { email = label.value; if ([email length] > 0) { [emailArray addObject:email]; } } //NSLog(@"EMAIL: %@",email); NSDictionary* personDict = [[NSDictionary alloc] initWithObjectsAndKeys: fullName,@"fullName",profileImage,@"userImage",phone,@"PhoneNumbers",birthDayStr,@"BirthDay",email,@"userEmailId", nil]; // NSLog(@"Response: %@",personDict); [self.contactsArray addObject:personDict]; } dispatch_async(dispatch_get_main_queue(), ^{ [self.tableViewRef reloadData]; }); } } }]; } 

swift 3 and Xcode 8你可以得到所有的联系人列表

 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") } } 

首先获取默认容器标识符,然后使用谓词匹配容器标识符

 let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey] let containerId = CNContactStore().defaultContainerIdentifier() let predicate: NSPredicate = CNContact.predicateForContactsInContainerWithIdentifier(containerId) let contacts = try CNContactStore().unifiedContactsMatchingPredicate(predicate, keysToFetch: keysToFetch) 

iOS中的CNContact

目标C

 #import "ViewController.h" #import <Contacts/Contacts.h> @interface ViewController () { NSMutableArray *arrayTableData; } @end @implementation ViewController -(void)viewDidLoad { [self fetchContactsandAuthorization]; } //This method is for fetching contacts from iPhone.Also It asks authorization permission. -(void)fetchContactsandAuthorization { // Request authorization to Contacts CNContactStore *store = [[CNContactStore alloc] init]; [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted == YES) { //keys with fetching properties NSArray *keys = @[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey]; NSString *containerId = store.defaultContainerIdentifier; NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId]; NSError *error; NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error]; if (error) { NSLog(@"error fetching contacts %@", error); } else { NSString *phone; NSString *fullName; NSString *firstName; NSString *lastName; UIImage *profileImage; NSMutableArray *contactNumbersArray = [[NSMutableArray alloc]init]; for (CNContact *contact in cnContacts) { // copy data to my custom Contacts class. firstName = contact.givenName; lastName = contact.familyName; if (lastName == nil) { fullName=[NSString stringWithFormat:@"%@",firstName]; }else if (firstName == nil){ fullName=[NSString stringWithFormat:@"%@",lastName]; } else{ fullName=[NSString stringWithFormat:@"%@ %@",firstName,lastName]; } UIImage *image = [UIImage imageWithData:contact.imageData]; if (image != nil) { profileImage = image; }else{ profileImage = [UIImage imageNamed:@"person-icon.png"]; } for (CNLabeledValue *label in contact.phoneNumbers) { phone = [label.value stringValue]; if ([phone length] > 0) { [contactNumbersArray addObject:phone]; } } NSDictionary* personDict = [[NSDictionary alloc] initWithObjectsAndKeys: fullName,@"fullName",profileImage,@"userImage",phone,@"PhoneNumbers", nil]; [arrayTableData addObject:[NSString stringWithFormat:@"%@",[personDict objectForKey:@"fullName"]]]; NSLog(@"The contactsArray are - %@",arrayTableData); } dispatch_async(dispatch_get_main_queue(), ^{ [tableViewContactData reloadData]; }); } } }]; } @end 

输出是

 The contactsArray are - ( "John Appleseed", "Kate Bell", "Anna Haro", "Daniel Higgins", "David Taylor", "Hank Zakroff" } 

@rocolitis的答案很快! 根据苹果公司的文件,他的回答是最正确的做法。

 let contactStore = CNContactStore() let keys = [CNContactPhoneNumbersKey, CNContactFamilyNameKey, CNContactGivenNameKey, CNContactNicknameKey] as [CNKeyDescriptor] let request = CNContactFetchRequest(keysToFetch: keys) try? contactStore.enumerateContacts(with: request) { (contact, error) in // Do something with contact } 

您应该首先检查您的联系人的访问权限!

 let authorization = CNContactStore.authorizationStatus(for: CNEntityType.contacts) switch authorization { case .authorized: break case .denied: break case .restricted: break case .notDetermined: break } 

对于swift var结果包含所有联系人

 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") } 

SWIFT 2

在iOS9中从联系人框架获取全名,电子邮件ID,电话号码,个人资料图片

注意没有名字的联系人也被处理。

步骤1

 import Contacts 

第2步

 func fetchContacts(completion: (result: NSMutableArray) -> Void ) { let finalArrayForContacts = NSMutableArray() let contactsArray = NSMutableArray() let requestForContacts = CNContactFetchRequest(keysToFetch: [CNContactIdentifierKey, CNContactFormatter.descriptorForRequiredKeysForStyle(CNContactFormatterStyle.FullName), CNContactPhoneNumbersKey ,CNContactThumbnailImageDataKey]) do{ try contactStore.enumerateContactsWithFetchRequest(requestForContacts) { (contactStore : CNContact, stop: UnsafeMutablePointer<ObjCBool>) -> Void in contactsArray.addObject(contactStore) } } catch { } if contactsArray.count > 0 { let formatter = CNContactFormatter() for contactTemp in contactsArray { let contactNew = contactTemp as! CNContact //Contact Name var stringFromContact = formatter.stringFromContact(contactNew) if stringFromContact == nil { stringFromContact = "Unnamed" } var imageData = NSData?() if contactNew.thumbnailImageData != nil{ imageData = contactNew.thumbnailImageData! }else{ // imageData = nil } var tempArray : NSArray = NSArray() if (contactNew.phoneNumbers).count > 0 { tempArray = ((contactNew.phoneNumbers as? NSArray)?.valueForKey("value").valueForKey("digits")) as! NSArray for i in 0 ..< tempArray.count { let newDict = NSMutableDictionary() let phoneNumber : String = (tempArray.objectAtIndex(i)) as! String if phoneNumber.characters.count > 0 { var test = false if phoneNumber.hasPrefix("+") { test = true } var resultString : String = (phoneNumber.componentsSeparatedByCharactersInSet(characterSet) as NSArray).componentsJoinedByString("") if test == true { resultString = "+\(resultString)" } newDict.setValue(resultString, forKey: "contact_phone") newDict.setValue(stringFromContact, forKey: "contact_name") newDict.setValue("0", forKey: "contact_select") newDict.setValue(imageData, forKey: "contact_image") finalArrayForContacts.addObject(newDict) } } }else{ // no number saved } } }else { print("No Contacts Found") } completion(result: finalArrayForContacts) } 

现在在iOS9 ABAddressBookRef已弃用,所以要从手机中获取所有联系人使用此框架,并添加此function,您将获得联系数组。

像这样在.h类中导入联系框架

 #import <Contacts/Contacts.h> 

然后在.m文件中添加此方法

  -(void)contactsFromAddressBook{ //ios 9+ CNContactStore *store = [[CNContactStore alloc] init]; [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted == YES) { //keys with fetching properties NSArray *keys = @[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey]; NSString *containerId = store.defaultContainerIdentifier; NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId]; NSError *error; NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error]; if (error) { NSLog(@"error fetching contacts %@", error); } else { NSString *phone; NSString *fullName; NSString *firstName; NSString *lastName; UIImage *profileImage; NSMutableArray *contactNumbersArray; for (CNContact *contact in cnContacts) { // copy data to my custom Contacts class. firstName = contact.givenName; lastName = contact.familyName; if (lastName == nil) { fullName=[NSString stringWithFormat:@"%@",firstName]; }else if (firstName == nil){ fullName=[NSString stringWithFormat:@"%@",lastName]; } else{ fullName=[NSString stringWithFormat:@"%@ %@",firstName,lastName]; } UIImage *image = [UIImage imageWithData:contact.imageData]; if (image != nil) { profileImage = image; }else{ profileImage = [UIImage imageNamed:@"person-icon.png"]; } for (CNLabeledValue *label in contact.phoneNumbers) { phone = [label.value stringValue]; if ([phone length] > 0) { [contactNumbersArray addObject:phone]; } } NSDictionary* personDict = [[NSDictionary alloc] initWithObjectsAndKeys: fullName,@"fullName",profileImage,@"userImage",phone,@"PhoneNumbers", nil]; [MutableArray__Contact addObject:personDict]; } dispatch_async(dispatch_get_main_queue(), ^ { NSLog(@"%@",ar_Contact); //[self.tableViewRef reloadData]; }); } } }]; } 

用这个方法调用contactsFromAddressBook函数

 [self contactsFromAddressBook]; 

联系人权限iOS 9 SWIFT 2

  let status : CNAuthorizationStatus = CNContactStore.authorizationStatusForEntityType(CNEntityType.Contacts) if status == CNAuthorizationStatus.NotDetermined{ contactStore.requestAccessForEntityType(CNEntityType.Contacts, completionHandler: { (temp: Bool, error : NSError?) -> Void in //call contacts fetching function }) }else if status == CNAuthorizationStatus.Authorized { //call contacts fetching function }) } else if status == CNAuthorizationStatus.Denied { } } 

我想这个代码工作正常。 我可以使用swift3最新的框架使用联系人使用此代码获取所有联系人详细信息:

 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) } 

科迪在Swift 3中的回应:

 import Contacts 

然后在你使用的任何函数中:

  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)") } }) 

这是flohei答案的 swift 3.0版本

 lazy var contacts: [CNContact] = { let contactStore = CNContactStore() let keysToFetch = [ CNContactFormatter.descriptorForRequiredKeys(for: .fullName), CNContactPostalAddressesKey, CNContactEmailAddressesKey, CNContactPhoneNumbersKey, CNContactImageDataAvailableKey, CNContactThumbnailImageDataKey] as [Any] // Get all the containers var allContainers: [CNContainer] = [] do { allContainers = try contactStore.containers(matching: 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.predicateForContactsInContainer(withIdentifier: container.identifier) do { let containerResults = try contactStore.unifiedContacts(matching: fetchPredicate, keysToFetch: keysToFetch as! [CNKeyDescriptor]) results.append(contentsOf: containerResults) } catch { print("Error fetching results for container") } } return results }() 

希望这可以帮助!