关于IOS获取本地通讯录信息(包含iOS9.0前后)

blog:developfan.com

简书:http://www.jianshu.com/u/9fed08d0ebfb   


在ios开发当中,获取用户本地的通讯录功能愈加频繁的出现,七两自己也在自己公司的项目当中遇到的获取本地的通讯录信息的功能(俗称“种子用户功能”,太可怕了)。对此七两总结了自己使用本地通讯录时的注意点,希望对大家有所帮助。

首先对于获取本地通讯录的信息,大苹果在ios9.0之后推出了另外的一个使用方式(controller),类似于之前searchcontroller与searchBar,对此七两在此分成两部分,ios9.0前与ios9.0后两部分进行总结。


一、iOS9.0前

先附上七两自己写得代码:
对于苹果对于通讯录的操作实现可以类比sqlite与sqlite3的管理实现方式,及我们在使用通讯录时需调用类似于sqlite3的管理对象,对此七两自 己习惯将对通讯录的操作过程写成单例,具体如下:

.h文件
#import 
#import 
#import 

typedef void(^YFAddressBookBlock)(BOOL canRead, ABAuthorizationStatus authorStatus);

@interface YFAddressBookManger : NSObject

@property (nonatomic, assign) ABAddressBookRef addressBook;
//单例类方法
+ (instancetype)shareManger;

//设置传值
- (void)canReadAddressBookWithBlock:(YFAddressBookBlock)block;

- (void)gotoSetting:(UIViewController *)vc;

@end
.m文件

#import "YFAddressBookManger.h"

@implementation YFAddressBookManger

+ (instancetype)shareManger{
    static YFAddressBookManger *manger = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!manger) {
            manger = [[YFAddressBookManger alloc]init];
        }
    });
    return manger;
}

- (id)init{
    self = [super init];
    if (self) {
        _addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
    }
    
    return self;
}

//获取读取权限
- (void)canReadAddressBookWithBlock:(YFAddressBookBlock)block{
    ABAuthorizationStatus authStatus = ABAddressBookGetAuthorizationStatus();
    if (authStatus == kABAuthorizationStatusNotDetermined) {
        ABAddressBookRequestAccessWithCompletion(_addressBook, ^(bool granted, CFErrorRef error) {
           dispatch_async(dispatch_get_main_queue(), ^{
               if (error) {
                   //拒绝访问
                   block(NO,kABAuthorizationStatusDenied);
               }else{
                   block(YES,0);
               }
           });
        });
    }else if (authStatus == kABAuthorizationStatusAuthorized){
        block(YES,0);
    }else{
        block(NO,authStatus);
    }
}

//去设置页面
- (void)gotoSetting:(UIViewController *)vc{
    NSString *appName = [[NSBundle mainBundle].infoDictionary valueForKey:@"CFBundleDisplayName"];
    if (!appName) appName = [[NSBundle mainBundle].infoDictionary valueForKey:@"CFBundleName"];
    NSString *message = [NSString stringWithFormat:@"请在%@的\"设置-隐私-通讯录\"选项中,\r允许%@访问你的通讯录。",[UIDevice currentDevice].model,appName];

    UIAlertController *alertVC = [[UIAlertController alloc]init];
    [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
    }];
    UIAlertAction *cancleAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        
    }];
    [alertVC addAction:cancleAction];
    [alertVC addAction:sureAction];
}
@end

后续引用通讯录中得数据至controller中的使用方式如下:
#pragma mark - 获取本地的通讯录数据
- (void)getDataSource{
    if (_dataSource == nil) {
        _dataSource = [NSMutableArray new];
    }
    [[YFAddressBookManger shareManger]canReadAddressBookWithBlock:^(BOOL canRead, ABAuthorizationStatus authorStatus) {
        if (canRead) {
            ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
            CFArrayRef allLinkPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
            CFIndex num = ABAddressBookGetPersonCount(addressBook);
            for (NSInteger i = 0; i < num; i++) {
                ABRecordRef  people = CFArrayGetValueAtIndex(allLinkPeople, i);
                ABMultiValueRef phones = ABRecordCopyValue(people, kABPersonPhoneProperty);
                
                for (int k = 0; k
如果需要其余的多余的单值属性需不同的字段,代码中的ABRecordCopyValue方法可以理解为C语言中得字典。即可根据不同的单值属性获取。

二、iOS9.0之后

苹果推荐ContactsUI使用,具体的使用方式如下:

pragma mark - 
/* 当选中一个联系人时,会执行该方法 
@param picker 选择联系人的控制器 
@param contact 选择的联系人 /
(void)contactPicker:(CNContactPickerViewController )picker didSelectContact:(CNContact )contact{
// 1.获取联系人的姓名   NSString *firstName = contact.givenName;
  NSString *lastName = contact.familyName;
  NSLog(@"%@ %@", firstName, lastName);
// 2.获取联系人的电话号码   NSArray *phoneNumers = contact.phoneNumbers;
   for (CNLabeledValue *labelValue in phoneNumers) {
       CNPhoneNumber *phoneNumber = labelValue.value; 
       NSString *phoneValue = phoneNumber.stringValue; 
       NSString *phoneLabel = labelValue.label;
       NSLog(@"%@ %@", phoneValue, phoneLabel);
  }
}
/* 当选中某一个联系人的某一个属性时,会执行该方法 
@param contactProperty 选中的联系人属性
*/
(void)contactPicker:(CNContactPickerViewController )picker didSelectContactProperty:(CNContactProperty )contactProperty{}


具体的细节使用如下:


// 1.获取授权状态
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
// 2.如果不是已经授权,则直接返回
if (status != CNAuthorizationStatusAuthorized) return;

// 3.获取联系人
// 3.1.创建联系人仓库
CNContactStore *store = [[CNContactStore alloc] init];

// 3.2.创建联系人的请求对象
// keys决定这次要获取哪些信息,比如姓名/电话
NSArray *fetchKeys = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:fetchKeys];

// 3.3.请求联系人
NSError *error = nil;
[store enumerateContactsWithFetchRequest:request error:&error usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
    // stop是决定是否要停止
    // 1.获取姓名
    NSString *firstname = contact.givenName;
    NSString *lastname = contact.familyName;
    NSLog(@"%@ %@", firstname, lastname);

    // 2.获取电话号码
    NSArray *phones = contact.phoneNumbers;

    // 3.遍历电话号码
    for (CNLabeledValue *labelValue in phones) {
        CNPhoneNumber *phoneNumber = labelValue.value;
        NSLog(@"%@ %@", phoneNumber.stringValue, labelValue.label);
    }
}];




你可能感兴趣的:(Object,-C)