iOS通讯录授权(区分iOS9前后版本)

做通讯录授权弹窗的时候,做了很多查询,所以想做一个防止自己过后忘记的总结,针对iOS不同版本进行使用区分(不包含UI部分)。

参考文章:https://www.jianshu.com/p/df0ea100c3da

iOS8及之前采用的是Addressbook,iOS9以后替换为Contact。其实具体字段中的名称是没有大的改动的,使用过程都相同,就是注意使用方法和具体字段名称的区分。

首先授权

在Xcode中打开项目,进入info列表页,添加通讯录授权权限 Privacy - Contacts Usage Description,其中提示文字可以自行编辑。

 

授权触发

#import <AddressBookUI/AddressBookUI.h> //引入头文件 iOS8
#import <ContactsUI/ContactsUI.h> //引入头文件 iOS9

//获取系统通讯录权限
//iOS8:
- (void)askUserWithSuccess:(void (^)())success failure:(void (^)())failure
{
    ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
    ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error){
        if(granted){
            dispatch_async(dispatch_get_main_queue(), ^{
                success();
            });
        }else{
            dispatch_async(dispatch_get_main_queue(), ^{
                failure();
            });
        }
    });
}
//iOS9:
- (void)askUserWithSuccess:(void (^)())success failure:(void (^)())failure
{
    [[[CNContactStore alloc]init] requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
        if(granted){
            dispatch_async(dispatch_get_main_queue(), ^{
                success();
            });
        }else{
            dispatch_async(dispatch_get_main_queue(), ^{
                failure();
            });
        }
    }];
}

iOS系统通讯录授权,在首次触发时弹出的为系统弹窗,无论用户是否授权,这个系统弹窗仅会弹出一次。所以需要自行根据用户授权状态进行相应处理。

在书写业务逻辑时,进入通讯录相关时,首先需要判断授权状态,然后根据授权状态进行后续处理,可能的情况:

1、第一次进入,还未授权,触发系统授权弹窗

2、用户同意 - > 进入后续通讯录读取等逻辑

3、用户拒绝 -> 可编写警告框进行状态提示等 (如果用户未对系统弹窗做出反应,默认是为拒绝)

在写的时候可以将iOS8及9做一个兼容,封装成一个方法,之后在方法中判断系统版本,进行后续的调用。

授权状态判断

iOS8及之前:https://www.cnblogs.com/yyyyyyyyqs/p/5562777.html ,这篇对iOS8之前的address框架描述详细,字段齐全

查询授权状态 :

ABAddressBookGetAuthorizationStatus函数可以查询对通讯录的访问权限
kABAuthorizationStatusNotDetermined用户还没有决定是否授权你的程序进行访问
kABAuthorizationStatusRestrictediOS设备上的家长控制或其它一些许可配置阻止程序与通讯录数据库进行交互
kABAuthorizationStatusDenied用户明确的拒绝了你的程序对通讯录的访问
kABAuthorizationStatusAuthorized用户已经授权给你的程序对通讯录进行访问

iOS9:https://www.jianshu.com/p/fadeb914d1ed ,这篇对contact框架解释较为详细,且对通讯录字段描述详细

CNAuthorizationStatusNotDetermined用户还没有决定是否授权你的程序进行访问
CNAuthorizationStatusRestrictediOS设备上的家长控制或其它一些许可配置阻止程序与通讯录数据库进行交互
CNAuthorizationStatusDenied用户明确的拒绝了你的程序对通讯录的访问
CNAuthorizationStatusAuthorized用户已经授权给你的程序对通讯录进行访问
#import <AddressBookUI/AddressBookUI.h> //引入头文件


//自定义状态监测方法,可用switch,此处使用if进行判断了
- (SXAddressBookAuthStatus)getAuthStatus
{
    ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
    
    if (status == kABAuthorizationStatusNotDetermined) {
        //NSLog(@"还没问呢");
        return kSXAddressBookAuthStatusNotDetermined;
    }else if (status == kABAuthorizationStatusAuthorized){
        //NSLog(@"已经授权");
        return kSXAddressBookAuthStatusAuthorized;
    }else if (status == kABAuthorizationStatusRestricted){
        //NSLog(@"iOS设备上一些许可配置阻止程序与通讯录数据库进行交互");
        return kSXAddressBookAuthStatusRestricted;
    }else{
        //NSLog(@"没有授权");
        return kSXAddressBookAuthStatusDenied;
    }
}

iOS9及之后:(字段同上,不多注释了)

#import <ContactsUI/ContactsUI.h> //插入头文件

//自定义方法
- (SXAddressBookAuthStatus)getAuthStatus
{
    CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
    
    if (status == CNAuthorizationStatusNotDetermined) {
        return kSXAddressBookAuthStatusNotDetermined;
    }else if (status == CNAuthorizationStatusAuthorized){
        return kSXAddressBookAuthStatusAuthorized;
    }else if (status == CNAuthorizationStatusDenied){
        return kSXAddressBookAuthStatusDenied;
    }else{
        return kSXAddressBookAuthStatusRestricted;
    }
}

获得授权之后读取通讯录内容,此处仅获取字段进行处理,后续的UI不做描述

通讯录内容字段:

姓名、昵称、公司等类型均为string

邮件,URL地址、地址、电话号码均为数组

iOS9:

- (NSArray *)getPersonInfoArray
{
    NSMutableArray *personArray = [NSMutableArray array];
    CNContactStore *contactStore = [[CNContactStore alloc] init];
    
    NSArray *keys = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey, CNContactNicknameKey,CNContactOrganizationNameKey, CNContactEmailAddressesKey,CNContactUrlAddressesKey,CNContactPostalAddressesKey];
//此处,需要获取哪些通讯录字段,需列出    

    CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
    
    [contactStore enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
        SXPersonInfoEntity *personEntity = [SXPersonInfoEntity new];
        
        //name string
        NSString *lastname = contact.familyName;
        NSString *firstname = contact.givenName;
        NSMutableString *fullname = [[NSString stringWithFormat:@"%@%@",lastname,firstname] mutableCopy];
        [fullname replaceOccurrencesOfString:@"(null)" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, fullname.length)];
        personEntity.name = fullname;
        personEntity.nickname = contact.nickname;
        personEntity.company = contact.organizationName;
        
        //email array
        NSArray *emailArray = contact.emailAddresses;
        NSMutableArray *emailAddress = [[NSMutableArray alloc]init];
        for (CNLabeledValue *labeledValue in emailArray) {
            NSString *emailContent = labeledValue.value;
            [emailAddress addObject:emailContent];
        }
        personEntity.email = emailAddress;
        
        //phone array
        NSMutableArray *fullPhoneStr = [[NSMutableArray alloc]init];
        for (CNLabeledValue *labeledValue in contact.phoneNumbers) {
            CNPhoneNumber *phoneNumer = labeledValue.value;
            NSString *phoneValue = phoneNumer.stringValue;
            phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@"+86" withString:@""];
            phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@"-" withString:@""];
            phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@"(" withString:@""];
            phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@")" withString:@""];
            phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@" " withString:@""];
            phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@" " withString:@""];
            
            [fullPhoneStr addObject:phoneValue];
        }
        personEntity.phone = fullPhoneStr;
        
        //地址 array todo
        NSMutableArray *postalAddress = [[NSMutableArray alloc]init];
        for (CNLabeledValue *labeledValue in contact.postalAddresses) {
            CNPostalAddress *postalAddr = labeledValue.value;
            NSString *address = [NSString stringWithFormat:@"%@\n%@\n%@\n%@\n%@",postalAddr.country,postalAddr.city,postalAddr.state,postalAddr.street,postalAddr.postalCode];
            
            [postalAddress addObject:address];
        }
        personEntity.address = postalAddress;
        
        //url array
        NSMutableArray *urlArray = [[NSMutableArray alloc]init];
        for (CNLabeledValue *labeledValue in contact.urlAddresses) {
            NSString *urlAddr = labeledValue.value;
            [urlArray addObject:urlAddr];
        }
        personEntity.website = urlArray;
        
        [personArray addObject:personEntity];
    }];
    return personArray;
}

iOS8:注意写法和iOS9是有区分的,字段获取方式不同

- (NSArray *)getPersonInfoArray
{
    ABAddressBookRef addressBook = ABAddressBookCreate();
    CFArrayRef peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook);
    CFIndex peopleCount = CFArrayGetCount(peopleArray);
    
    NSMutableArray *personArray = [NSMutableArray array];
    for (int i = 0; i < peopleCount; i++) {
        SXPersonInfoEntity *personEntity = [SXPersonInfoEntity new];
        ABRecordRef person = CFArrayGetValueAtIndex(peopleArray, i);
        
        //名字 string
        NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
        NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
        NSMutableString *fullname = [[NSString stringWithFormat:@"%@%@",lastName,firstName] mutableCopy];
        [fullname replaceOccurrencesOfString:@"(null)" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, fullname.length)];
        personEntity.name = fullname;
        
        //昵称 string
        NSString *nickname = (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonNicknameProperty);
        personEntity.nickname = nickname;
        
        //电话号码 array
        NSMutableArray *phoneArray = [[NSMutableArray alloc]init];
        ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
        for (NSInteger j=0; j<ABMultiValueGetCount(phones); j++) {
            NSString *phoneValue = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(phones, j));
            phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@"+86" withString:@""];
            phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@"-" withString:@""];
            phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@"(" withString:@""];
            phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@")" withString:@""];
            phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@" " withString:@""];
            phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@" " withString:@""];
            [phoneArray addObject:phoneValue];
        }
        personEntity.phone = phoneArray;
        
        //公司 string
        NSString *organization = (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonOrganizationProperty);
        personEntity.company = organization;
        
        //email array
        NSMutableArray *emailArray = [[NSMutableArray alloc]init];
        ABMultiValueRef emails= ABRecordCopyValue(person, kABPersonEmailProperty);
        for (NSInteger j=0; j<ABMultiValueGetCount(emails); j++) {
            NSString *email = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(emails, j));
            [emailArray addObject:email];
        }
        personEntity.email = emailArray;
        
        //address/地址 array
        NSMutableArray *addressArray = [[NSMutableArray alloc]init];
        ABMultiValueRef address = ABRecordCopyValue(person, kABPersonAddressProperty);
        for (int j=0; j<ABMultiValueGetCount(address); j++) {
            //地址类型
            NSString *type = (__bridge NSString *)(ABMultiValueCopyLabelAtIndex(address, j));
            NSDictionary * tempDic = (__bridge NSDictionary *)(ABMultiValueCopyValueAtIndex(address, j));
            //地址字符串,可以按需求格式化
            NSString *adress = [NSString stringWithFormat:@"%@\n%@\n%@\n%@\n%@",[tempDic valueForKey:(NSString*)kABPersonAddressCountryKey],[tempDic valueForKey:(NSString*)kABPersonAddressStateKey],[tempDic valueForKey:(NSString*)kABPersonAddressCityKey],[tempDic valueForKey:(NSString*)kABPersonAddressStreetKey],[tempDic valueForKey:(NSString*)kABPersonAddressZIPKey]];
            [addressArray addObject:adress];
        }
        personEntity.address = addressArray;
        
        //url array
        NSMutableArray *urlArray = [[NSMutableArray alloc]init];
        ABMultiValueRef url = ABRecordCopyValue(person, kABPersonURLProperty);
        for (int m = 0; m < ABMultiValueGetCount(url); m++)
        {
            NSString * urlLabel = (__bridge NSString*)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(url, m));
            NSString * urlContent = (__bridge NSString*)ABMultiValueCopyValueAtIndex(url,m);
            [urlArray addObject:urlContent];
        }
        personEntity.website = urlArray;
        
        [personArray addObject:personEntity];
        
        CFRelease(phones);
        CFRelease(emails);
        CFRelease(url);
        CFRelease(address);
    }
    CFRelease(addressBook);
    CFRelease(peopleArray);
    return personArray;
}

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值