通讯录读取
ContactTool.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef void(^AddressBook)(BOOL successed, NSArray<__kindof NSDictionary*> *addressBookArray);
UIKIT_EXTERN NSString *const Contact_Name;
UIKIT_EXTERN NSString *const Contact_Phone;
UIKIT_EXTERN NSString *const Contact_Lowercase_Name;
@interface ContactTool : NSObject
//读取通讯录,保存为姓名,电话,姓名拼音小写字典
+ (void)pickAddressBookCompletion:(AddressBook)completion;
//标准化为大陆号码,去除+86和"-"还有" "
+ (NSString *)phoneNumberFormat:(NSString *)phone;
//转换汉字成拼音
+ (NSString *)transformToPinyin:(NSString *)string;
@end
###ContactTool.m
NSString *const Contact_Name = @"name";
NSString *const Contact_Phone = @"phone";
NSString *const Contact_Lowercase_Name = @"lowercaseName";
@implementation ContactTool
#pragma mark - AdressBook DataList读取通讯录
+ (void)pickAddressBookCompletion:(AddressBook)completion {
//创建一个电话本的参考
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
//创建一个信号
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
//申请接入闭包
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
//接入成功发送信号
dispatch_semaphore_signal(sema);
});
//信号开始是0 发送出一个信号变成-1 信号值小于0时继续执行,如果没有得到信号,等待FOREVER
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
//检查权限
if (ABAddressBookGetAuthorizationStatus() != kABAuthorizationStatusAuthorized) {
completion(NO,nil);
return;
}
//检查是否成功创建
if (addressBookRef == nil) {
return;
}
//成功则拷贝电话本
[self copyAddressBook:addressBookRef completion:completion];
}
+ (void)copyAddressBook:(ABAddressBookRef)addressBook completion:(AddressBook)completion {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//C Float Index 使用有符号long的数目作为索引 获得总人数
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);
//
CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
//
NSMutableArray *addressBookArray = [NSMutableArray array];
for (int i = 0; i < numberOfPeople; ++i) {
ABRecordRef person = CFArrayGetValueAtIndex(people, i);
NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
NSMutableString *compositeName = nil;
//判断是否存在空
if (firstName == nil && lastName == nil) {
compositeName = [NSMutableString stringWithString:@"#"];
}else if (firstName == nil){
compositeName = [NSMutableString stringWithFormat:@"%@",lastName];
}else if (lastName == nil){
compositeName = [NSMutableString stringWithFormat:@"%@",firstName];
}else {
compositeName = [NSMutableString stringWithFormat:@"%@%@",lastName,firstName];
}
//取出电话号码
ABMultiValueRef phone = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSInteger phoneCount = ABMultiValueGetCount(phone);
//
for (int i = 0; i < phoneCount; ++i) {
NSString *phoneNumber = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(phone, i));
phoneNumber = [self phoneNumberFormat:phoneNumber];
//模拟器测试需要注销掉if
//RegxTool是个自己写的正则校验函数
if ([RegxTool validPhoneNumber:phoneNumber]) {
NSString *lowercaseName = [[self transformToPinyin:compositeName] lowercaseString];
NSDictionary *dict = @{Contact_Name:compositeName,Contact_Phone:phoneNumber,Contact_Lowercase_Name:lowercaseName};
[addressBookArray addObject:dict];
}
}
}
//
if (addressBookArray.count > 0) {
//字典数组按KEY排序
NSArray *sortedArray = [self sortArray:addressBookArray withKey:(NSString *)Contact_Lowercase_Name];
[addressBookArray removeAllObjects];
[addressBookArray addObjectsFromArray:sortedArray];
//返回结果
dispatch_async(dispatch_get_main_queue(), ^{
completion(YES, addressBookArray);
});
}
});
}
+ (NSString *)phoneNumberFormat:(NSString *)phone {
NSMutableString *tempPhone = [NSMutableString stringWithString:phone];
NSRange prefixRange = [tempPhone rangeOfString:@"+86"];
if (prefixRange.location != NSNotFound) {
[tempPhone deleteCharactersInRange:prefixRange];
}
NSRange spaceRange = [tempPhone rangeOfString:@" "];
while (spaceRange.location != NSNotFound) {
[tempPhone deleteCharactersInRange:spaceRange];
spaceRange = [tempPhone rangeOfString:@" "];
}
NSRange linkRange = [tempPhone rangeOfString:@"-"];
while (linkRange.location != NSNotFound) {
[tempPhone deleteCharactersInRange:linkRange];
linkRange = [tempPhone rangeOfString:@" "];
}
return tempPhone;
}
+ (NSString *)transformToPinyin:(NSString *)string {
NSString *regularString = @"^[A-Za-z0-9\\p{Z}\\p{P}]+$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regularString];
BOOL needTransform = ![predicate evaluateWithObject:string];
//
NSMutableString *mutableString = [NSMutableString stringWithString:string];
if (needTransform) {
CFStringTransform((CFMutableStringRef)mutableString, NULL, kCFStringTransformToLatin, false);
CFStringTransform((CFMutableStringRef)mutableString, NULL, kCFStringTransformStripCombiningMarks, false);
}
return mutableString;
}
+ (NSArray *)sortArray:(NSArray *)array withKey:(NSString *)key {
NSSortDescriptor *sortDesc = [NSSortDescriptor sortDescriptorWithKey:key ascending:YES];
NSArray *sortDescArr = [NSArray arrayWithObject:sortDesc];
NSArray *sortedArr = [array sortedArrayUsingDescriptors:sortDescArr];
return sortedArr;
}
@end
权限检查代码
由于在读取通讯录的过程中,并不一定有读取的权限,如果使用以下代码,在真机调试中可以顺利在获得权限后读取,模拟器中不行,原因:
由于闭包还未返回,代码已经顺序执行,addressBook在顺序执行的过程中始终为nil
- (void)pickAddressBook{
//读取通讯录权限
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
//请求完成闭包
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
CFErrorRef *error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
//自定义的拷贝函数
[self copyAddressBook:addressBook];
});
}else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized){
CFErrorRef *error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
//自定义的拷贝函数
[self copyAddressBook:addressBook];
}else{
//读取失败提示
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"翼支付" message:@"通讯录读取" cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
});
}
}
通讯录校验代码
电话号码去+86和-
+ (NSString *)phoneNumberFormat:(NSString *)phone;
电话号码正则校验
+ (BOOL)validPhoneNumber:(NSString *)phone{
NSString *regx = @"^[0-9]{11}$";
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regx];
return [pred evaluateWithObject:phone];
return NO;
}
[正则表达式常用校验][^1]
[^1]: