• 主页
  • 系列总集
  • OpenCV
  • CMake
  • iOS
  • Java
  • 前端
所有文章 关于我

  • 主页
  • 系列总集
  • OpenCV
  • CMake
  • iOS
  • Java
  • 前端

通讯录读取

2015-10-27

通讯录读取

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]:

赏

请问老板还招人么(/ω\)

支付宝
微信
  • iOS
  • Contact
  • Tips

扫一扫,分享到微信

微信分享二维码
设置Button的标题
Hello World
© 2021 Alan Li
Hexo Theme Yilia by Litten
  • 所有文章
  • 关于我

tag:

  • iOS
  • Java
  • Collection
  • Python
  • Shell
  • CMake
  • Memory
  • JavaScript
  • Architecture
  • AnchorPoint
  • Android
  • Web
  • Annotation
  • AFNetworking
  • Window
  • ViewController
  • AutoLayout
  • Dozer
  • CoreAnimation
  • Cycle Retain
  • Block
  • UI
  • IDE
  • FrontEnd
  • CSS
  • Category
  • TableViewCell
  • Security
  • Net
  • JSP
  • Spring
  • C
  • MyBatis
  • Date
  • React
  • GCD
  • UITouch
  • Gesture
  • UIControl
  • Git
  • HTML
  • HTTPS
  • HTTP
  • Servlet
  • Server
  • DataBase
  • MySQL
  • Linux
  • Tutorial
  • Ajax
  • Type
  • JQuery
  • JSON
  • Exception
  • Parameter
  • Reflect
  • Thread
  • Sort
  • KVO
  • MKMapKit
  • Overlay
  • Maven
  • Configure
  • Tips
  • Transaction
  • Swift
  • NavigationBar
  • Nginx
  • Runtime
  • OpenCV
  • Property
  • Playground
  • Protocol
  • Redux
  • ScrollView
  • Session
  • Cookie
  • Shiro
  • Error
  • Singleton
  • RegEx
  • StackView
  • StatusBar
  • Base64
  • Socket
  • TCP
  • IP
  • TextField
  • CALayer
  • UILabel
  • View
  • Animation
  • Xcode
  • Hexo
  • Terminal
  • OC
  • Device
  • Log
  • Image
  • JUnit
  • Oval
  • Archive
  • XSS
  • Compiler
  • Aspect
  • Responder
  • Class
  • FireWall
  • RetainCount
  • Const
  • Frame
  • String
  • Symbols
  • Framework
  • CocoaPods
  • Unity
  • Message
  • Button
  • AuthorizationStatus
  • Struct
  • XCTest
  • NSNotification
  • Contact

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

我写的,大概率是错的。。。。。