博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS-封装系统通讯录调用
阅读量:4135 次
发布时间:2019-05-25

本文共 8064 字,大约阅读时间需要 26 分钟。

在项目中有的地方会用到获取通讯里面的某个联系人的联系方式,这里我们稍微封装一下这个方法。

第一步:我们需要获取通讯录权限

info.plist文件中,添加 key : Privacy - Contacts Usage Description,value:方便用户从通讯录选取要保存的号码,如下图:

在这里插入图片描述
第二步:新建通讯录管理类

1、新建一个ContactManager

添加两个Block,用于回调权限和联系人号码

/** * 通讯录权限Block * * @param isAuthorization 是否有权限;  YES:有权限;   NO:无权限 */typedef void(^AddressBookAuthorization)(BOOL isAuthorization);/** * 通讯录号码Block * * @param phoneNumber 号码 */typedef void(^AddressBookOfPhoneNumberBlock)(NSString *phoneNumber);

添加两个方法,用于获取权限和弹出通讯录列表

/** * 模态弹出通讯录列表页 * * @param addressBookOfPhoneNumber block */- (void)presentAddressBookViewControllerWithPhoneNumber:(AddressBookOfPhoneNumberBlock)addressBookOfPhoneNumber;/** * 获取通讯录权限方法,可以单独使用 * * @param contactAuthorization block */- (void)getAddressBookAuthorization:(AddressBookAuthorization)contactAuthorization;

2、获取通讯录权限问题

获取通讯录权限的时候,判断系统版本,当veision >= 9.0 时,使用CNAuthorizationStatus;否则使用ABAuthorizationStatus

- (void)getAddressBookAuthorization:(AddressBookAuthorization)contactAuthorization{
NSString *version = [UIDevice currentDevice].systemVersion; if (version.doubleValue >= 9.0) {
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]; if (status == CNAuthorizationStatusNotDetermined) {
CNContactStore *store = [[CNContactStore alloc] init]; [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
//第一次获取权限判断,点击 “不允许” 则 granted = NO;点击 “好” 则 granted = YES; contactAuthorization(granted); }]; } else if (status == CNAuthorizationStatusAuthorized) {
//有权限 contactAuthorization(YES); } else {
//无权限 //NSLog(@"iOS 9 later 您未开启通讯录权限,请前往设置中心开启"); contactAuthorization(NO); } } else {
ABAddressBookRef bookref = ABAddressBookCreateWithOptions(NULL, NULL); ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus(); if (status == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(bookref, ^(bool granted, CFErrorRef error) {
contactAuthorization(granted); }); } if (status == kABAuthorizationStatusAuthorized) {
contactAuthorization(YES); }else{
//NSLog(@"iOS 9 before 您未开启通讯录权限,请前往设置中心开启"); contactAuthorization(NO); } }}

3、调起通讯录列表页

获取通讯录列表的时候,同样判断系统版本,当veision >= 9.0 时,使用CNContactPickerViewController;否则使用ABPeoplePickerNavigationController

- (void)presentAddressBookViewControllerWithPhoneNumber:(AddressBookOfPhoneNumberBlock)addressBookOfPhoneNumber{
[self getAddressBookAuthorization:^(BOOL isAuthorization) {
if (isAuthorization) {
[self presentABPeoplePickerOrCNContactPickerControllerWithPhoneNumber:addressBookOfPhoneNumber]; } else {
[self setContactAuthorization]; } }];}
- (void)presentABPeoplePickerOrCNContactPickerControllerWithPhoneNumber:(AddressBookOfPhoneNumberBlock)phoneNumberBlock{
NSString *version = [UIDevice currentDevice].systemVersion; //主线程刷新UI dispatch_async(dispatch_get_main_queue(), ^{
self.phoneNumberBlock = phoneNumberBlock; if (version.doubleValue >= 9.0) {
//iOS 9 之后 CNContactPickerViewController *picker = [[CNContactPickerViewController alloc] init]; picker.delegate = self; //picker.predicateForSelectionOfContact = [NSPredicate predicateWithFormat:@"emailAddresses.@count == 1"]; //picker.predicateForEnablingContact = [NSPredicate predicateWithFormat:@"emailAddresses.@count > 0"]; //picker.predicateForSelectionOfProperty = [NSPredicate predicateWithFormat:@"(key == 'emailAddresses') AND (value LIKE '*@mac.com')"]; picker.displayedPropertyKeys = @[CNContactPhoneNumbersKey];//只显示手机号 [KeyWidow.rootViewController presentViewController:picker animated:YES completion:nil]; } else {
//iOS 9 之前 ABPeoplePickerNavigationController *picker = [ABPeoplePickerNavigationController new]; picker.peoplePickerDelegate = self; picker.displayedProperties = @[[NSNumber numberWithInt:kABPersonPhoneProperty]]; [KeyWidow.rootViewController presentViewController:picker animated:YES completion:nil]; } });}

4、代理方法回调

#pragma mark - CNContactPickerDelegate- (void)contactPickerDidCancel:(CNContactPickerViewController *)picker{
[picker dismissViewControllerAnimated:YES completion:nil];}- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty;{
//注意:这里和displayedPropertyKeys属性设置相对应;只有 CNPhoneNumber 类型,如果添加别的类型,需要加类型判断,否则可能crash;例如:通讯录中的日期、邮箱... CNPhoneNumber *phoneNumber = contactProperty.value; NSString *phoneStr = phoneNumber.stringValue; //回调block,把号码带回去 if (self.phoneNumberBlock) {
self.phoneNumberBlock(phoneStr); }}#pragma mark - ABPeoplePickerNavigationControllerDelegate- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker{
[peoplePicker dismissViewControllerAnimated:YES completion:nil];}// 当用户选中某一个联系人时会执行该方法,并且选中联系人后会直接退出控制器//- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person{
////}// 当用户选中某一个联系人的某一个属性时会执行该方法,并且选中属性后会退出控制器- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{
[self peoplePickerNavigationControllerDidCancel:peoplePicker]; ABMultiValueRef phones = ABRecordCopyValue(person, property); CFIndex phoneCount = ABMultiValueGetCount(phones); NSString *phoneValue = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, identifier); //回调block,把号码带回去 if (self.phoneNumberBlock) {
self.phoneNumberBlock(phoneValue); } CFRelease(phones);}

5、处理未开通通讯录权限情况

- (void)setContactAuthorization{
//主线程刷新UI dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"您没有开启通讯录权限,去开通权限!" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"不了" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]; UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"这就去" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{
} completionHandler:^(BOOL success) {
}]; } else {
// Fallback on earlier versions [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; } }]; [alert addAction:action1]; [alert addAction:action2]; [KeyWidow.rootViewController presentViewController:alert animated:YES completion:nil]; });}

6、外部使用该封装类

//在外部使用该封装类,需要强引用,否则对象会提前释放后,导致block提前释放,以至于无法回调@property (nonatomic, strong) ContactManager *contactManager;
self.contactManager = [[ContactManager alloc] init];
[self.contactManager presentAddressBookViewControllerWithPhoneNumber:^(NSString * _Nonnull phoneNumber) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"%@",phoneNumber); }); }];

也可以使用单例写法,这时候需要在ContactManager类中实现创建单例方法:

[[ContactManager shareAddressBook] presentAddressBookViewControllerWithPhoneNumber:^(NSString * _Nonnull phoneNumber) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"%@",phoneNumber); }); }];

7、Demo下载地址:。

转载地址:http://dgivi.baihongyu.com/

你可能感兴趣的文章
阅读笔记《C++标准程序库》
查看>>
基于mirror driver的windows屏幕录像
查看>>
C语言8
查看>>
Qt实现简单延时
查看>>
qml有关矩形说明
查看>>
在qt中使用QSplitter设置初始比例setStretchFactor失效的解决方法
查看>>
repeater的使用
查看>>
qt msvc编译中文乱码解决
查看>>
qt中TextField输入框无法输入中文解决办法
查看>>
qt实现点击出现窗口,点击其他任何地方窗口消失
查看>>
QML DropArea拖拉文件事件
查看>>
CORBA links
查看>>
读后感:>
查看>>
ideas about sharing software
查看>>
different aspects for software
查看>>
To do list
查看>>
Study of Source code
查看>>
如何使用BBC英语学习频道
查看>>
spring事务探索
查看>>
浅谈Spring声明式事务管理ThreadLocal和JDKProxy
查看>>