iOS通讯录(纯纯的干货)
一、iOS8.0
1、访问用户通讯录的两个框架
(1)AddressBookUI.framework
提供了联系人列表界面、联系人详情界面、添加联系人界面等,一般用于选择联系人
(2)AddressBook.framework
<1>纯C语言的API,仅仅是获得联系人数据
<2>没有提供UI界面展示,需要自己搭建联系人展示界面
<3>里面的数据类型大部分基于Core Foundation框架,使用起来非常不方便
(3)从iOS6开始,需要得到用户的授权才能访问通讯录(没UI界面的),因此在使用之前,需要检查用户是否已经授权
获得通讯录的授权状态:ABAddressBookGetAuthorizationStatus()
2、使用AddressBookUI.framework示例
#import "ViewController.h" #import <AddressBookUI/AddressBookUI.h> @interface ViewController () <ABPeoplePickerNavigationControllerDelegate> @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { //创建通讯录控制器 //弹出控制器 ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc]init]; //设置代理 picker.peoplePickerDelegate = self; //展示通讯录界面 [self presentViewController:picker animated:YES completion:nil]; } //选中一个人的基本信息就会调用 //参数1:控制器 参数2:选择的person的信息 - (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person { /* 1、关于内存的管理:静态分析工具 2、因为是C语言的API(CoreFoundation),所有使用了create、copy等获取的对象都需要释放 -> CFRelease 3、桥接 __bridge 默认桥接 __bridge_transfer 桥接 coreF -> ocF 转让对象的所有权(释放权) __bridge_retained 桥接 ocF -> coreF 转让对象的所有权 */ //返回的ABRecordRef是一条记录,包括了一个人的所有信息字段 //通过“函数”获得姓名 CFStringRef strfirst = ABRecordCopyValue(person, kABPersonFirstNameProperty); CFStringRef strlast = ABRecordCopyValue(person, kABPersonLastNameProperty); //在桥接时,转让了对象的所有权,转给了OC来管理(自动释放了) NSString *strF = (__bridge_transfer NSString *)(strfirst); NSString *strL = (__bridge_transfer NSString *)(strlast); NSLog(@"%@ %@",strF,strL); //电话号码:ABMultiValueRef 封装一个保存了很多电话的一个类型,类似OC中的数组 ABMultiValueRef multiValues = ABRecordCopyValue(person, kABPersonPhoneProperty); //获得这个集合的数量(电话号码的数量) CFIndex index = ABMultiValueGetCount(multiValues); //遍历集合,打印电话 for (CFIndex i = 0; i < index; i++) { CFStringRef strPhone = ABMultiValueCopyValueAtIndex(multiValues, i); NSString *phoneStr = (__bridge_transfer NSString *)(strPhone); NSLog(@"%@",phoneStr); } //释放内存前,先判断该字段存在 if (multiValues != NULL) { CFRelease(multiValues); } } //选择中一个人信息的属性才会调用 //注意点:如果实现“选中个人信息的代理方法” 当前方法不执行,因为属性界面不会显示 - (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier { NSLog(@"property %zd",property); } //点击取消了 就会调用 - (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker { NSLog(@"peoplePickerNavigationControllerDidCancel"); }
3、使用AddressBook.framework框架示例
#import "ViewController.h" #import <AddressBook/AddressBook.h> @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //获取用户的授权:授权状态 /* kABAuthorizationStatusNotDetermined = 0, // deprecated, use CNAuthorizationStatusNotDetermined kABAuthorizationStatusRestricted, // deprecated, use CNAuthorizationStatusRestricted kABAuthorizationStatusDenied, // deprecated, use CNAuthorizationStatusDenied kABAuthorizationStatusAuthorized // 已经授权 */ //通过函数获得授权状态 ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus(); if (status == kABAuthorizationStatusNotDetermined) { ABAddressBookRef book = ABAddressBookCreateWithOptions(NULL, NULL); //申请授权 //参数1 通讯录对象 参数2block 回调 ABAddressBookRequestAccessWithCompletion(book, ^(bool granted, CFErrorRef error) { if (granted) { NSLog(@"授权成功!"); }else{ NSLog(@"授权失败!"); } }); } } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { //获取联系人信息 //获得姓名 //通讯录是单例,在哪里获取都是一样的 ABAddressBookRef book = ABAddressBookCreateWithOptions(NULL, NULL); //获取所有人的信息 CFArrayRef allpeople = ABAddressBookCopyArrayOfAllPeople(book); //数量 CFIndex count = CFArrayGetCount(allpeople); for (CFIndex i = 0; i <count ; i++) { //获得没一条记录 ABRecordRef record = CFArrayGetValueAtIndex(allpeople, i); //获得姓名 CFStringRef strFirst = ABRecordCopyValue(record, kABPersonFirstNameProperty); NSString *str = (__bridge_transfer NSString *)strFirst; NSLog(@"%@",str); //获得电话号码 ABMultiValueRef multivalue = ABRecordCopyValue(record, kABPersonPhoneProperty); for (CFIndex i = 0; i < ABMultiValueGetCount(multivalue); i++) { CFStringRef phoneStr = ABMultiValueCopyValueAtIndex(multivalue, i); NSString *phone = (__bridge_transfer NSString *)(phoneStr); NSLog(@"%@",phone); } CFRelease(multivalue); } CFRelease(allpeople); CFRelease(book); } @end
二、iOS9.0
1、访问用户通讯录的两个框架
(1)ContactsUI
<1>AddressBookUI的升级,不需要授权
<2>通过代理返回需要的数据
(2)Contacts
AddressBook.framework 的升级
2、ContactsUI示例
#import "ViewController.h" #import <ContactsUI/ContactsUI.h> @interface ViewController ()<CNContactPickerDelegate> @end @implementation ViewController - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { //不需要授权 //创建通讯录控制器 CNContactPickerViewController *picker = [[CNContactPickerViewController alloc]init]; //设置代理拿到数据本身 picker.delegate = self; //展示通讯录 [self presentViewController:picker animated:YES completion:nil]; } //实现代理方法 //选择一个联系人的基本信息 - (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact; { //重点注意contact的类型和属性 NSArray *allArray = contact.phoneNumbers; for (CNLabeledValue * labeledValue in allArray) { CNPhoneNumber *num = labeledValue.value; NSLog(@"num = %@",num.stringValue); NSLog(@"===%@ ===%@",labeledValue.value,labeledValue.label); } } //选择一个联系人属性信息 - (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty; { NSLog(@"didSelectContactProperty"); } @end
3、Contacts示例
#import "ViewController.h" #import <Contacts/Contacts.h> @interface ViewController () @property (nonatomic, strong) CNContactStore *store; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //获取授权状态 CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]; //如果没有授权过需要请求用户的授权 CNContactStore *store = [[CNContactStore alloc]init]; self.store = store; if (status == CNAuthorizationStatusNotDetermined) { //请求授权 [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted) { NSLog(@"授权成功!"); }else{ NSLog(@"授权失败!"); } }]; } } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { //name phone CNContactFetchRequest *request = [[CNContactFetchRequest alloc]initWithKeysToFetch:@[CNContactGivenNameKey,CNContactPhoneNumbersKey]]; //参数1 封装查询请求 [self.store enumerateContactsWithFetchRequest: request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) { //返回的数据 CNContact NSLog(@"%@",contact.givenName); NSLog(@"%@",contact.phoneNumbers); }]; } @end