本文共 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/