iOS通讯录开发

作者: 千煌89 | 来源:发表于2015-03-25 10:48 被阅读31936次

场景一:直接选择一个联系人的电话号码

这里不需要先获取所有的联系人自己做联系人列表,直接使用系统自带的AddressBookUI/ABPeoplePickerNavigationController.h就好。

首先需要引入如下三个文件

#import <AddressBookUI/ABPeoplePickerNavigationController.h>
#import <AddressBook/ABPerson.h>
#import <AddressBookUI/ABPersonViewController.h>

然后初始化ABPeoplePickerNavigationController。

ABPeoplePickerNavigationController *nav = [[ABPeoplePickerNavigationController alloc] init];
nav.peoplePickerDelegate = self;
if(IOS8_OR_LATER){
    nav.predicateForSelectionOfPerson = [NSPredicate predicateWithValue:false];
}
[self presentViewController:nav animated:YES completion:nil];

在iOS8之后,需要添加nav.predicateForSelectionOfPerson = [NSPredicate predicateWithValue:false];这一段代码,否则选择联系人之后会直接dismiss,不能进入详情选择电话。

最后设置代理

//取消选择
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
    [peoplePicker dismissViewControllerAnimated:YES completion:nil];
}

iOS8下

- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {
    ABMultiValueRef phone = ABRecordCopyValue(person, kABPersonPhoneProperty);
    long index = ABMultiValueGetIndexForIdentifier(phone,identifier);
    NSString *phoneNO = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phone, index);
    
    if ([phoneNO hasPrefix:@"+"]) {
        phoneNO = [phoneNO substringFromIndex:3];
    }
    
    phoneNO = [phoneNO stringByReplacingOccurrencesOfString:@"-" withString:@""];
    NSLog(@"%@", phoneNO);
    if (phone && [ZXValidateHelper checkTel:phoneNO]) {
        phoneNum = phoneNO;
        [self.tableView reloadData];
        [peoplePicker dismissViewControllerAnimated:YES completion:nil];
        return;
    }
}

- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person
{
    ABPersonViewController *personViewController = [[ABPersonViewController alloc] init];
    personViewController.displayedPerson = person;
    [peoplePicker pushViewController:personViewController animated:YES];
}

iOS7下

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
    return YES;
}

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
    ABMultiValueRef phone = ABRecordCopyValue(person, kABPersonPhoneProperty);
    long index = ABMultiValueGetIndexForIdentifier(phone,identifier);
    NSString *phoneNO = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phone, index);
    if ([phoneNO hasPrefix:@"+"]) {
        phoneNO = [phoneNO substringFromIndex:3];
    }
    
    phoneNO = [phoneNO stringByReplacingOccurrencesOfString:@"-" withString:@""];
    NSLog(@"%@", phoneNO);
    if (phone && [ZXValidateHelper checkTel:phoneNO]) {
        phoneNum = phoneNO;
        [self.tableView reloadData];
        [peoplePicker dismissViewControllerAnimated:YES completion:nil];
        return NO;
    }
    return YES;
}
效果演示

场景二:读取通讯录

这里需要读取通讯录数据。
首先引入头文件
#import <AddressBook/AddressBook.h>

其次根据权限生成通讯录

- (void)loadPerson
{
    ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
    
    if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
        ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error){
            
            CFErrorRef *error1 = NULL;
            ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error1);
            [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(), ^{
            // 更新界面
            [hud turnToError:@"没有获取通讯录权限"];
        });
    }
}

然后循环获取每个联系人的信息,建议自己建个model存起来。

- (void)copyAddressBook:(ABAddressBookRef)addressBook
{
    CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);
    CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
    
    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));
        
      //读取middlename
        NSString *middlename = (NSString*)ABRecordCopyValue(person, kABPersonMiddleNameProperty);
        //读取prefix前缀
        NSString *prefix = (NSString*)ABRecordCopyValue(person, kABPersonPrefixProperty);
        //读取suffix后缀
        NSString *suffix = (NSString*)ABRecordCopyValue(person, kABPersonSuffixProperty);
        //读取nickname呢称
        NSString *nickname = (NSString*)ABRecordCopyValue(person, kABPersonNicknameProperty);
        //读取firstname拼音音标
        NSString *firstnamePhonetic = (NSString*)ABRecordCopyValue(person, kABPersonFirstNamePhoneticProperty);
        //读取lastname拼音音标
        NSString *lastnamePhonetic = (NSString*)ABRecordCopyValue(person, kABPersonLastNamePhoneticProperty);
        //读取middlename拼音音标
        NSString *middlenamePhonetic = (NSString*)ABRecordCopyValue(person, kABPersonMiddleNamePhoneticProperty);
        //读取organization公司
        NSString *organization = (NSString*)ABRecordCopyValue(person, kABPersonOrganizationProperty);
        //读取jobtitle工作
        NSString *jobtitle = (NSString*)ABRecordCopyValue(person, kABPersonJobTitleProperty);
        //读取department部门
        NSString *department = (NSString*)ABRecordCopyValue(person, kABPersonDepartmentProperty);
        //读取birthday生日
        NSDate *birthday = (NSDate*)ABRecordCopyValue(person, kABPersonBirthdayProperty);
        //读取note备忘录
        NSString *note = (NSString*)ABRecordCopyValue(person, kABPersonNoteProperty);
        //第一次添加该条记录的时间
        NSString *firstknow = (NSString*)ABRecordCopyValue(person, kABPersonCreationDateProperty);
        NSLog(@"第一次添加该条记录的时间%@\n",firstknow);
        //最后一次修改該条记录的时间
        NSString *lastknow = (NSString*)ABRecordCopyValue(person, kABPersonModificationDateProperty);
        NSLog(@"最后一次修改該条记录的时间%@\n",lastknow);
        
        //获取email多值
        ABMultiValueRef email = ABRecordCopyValue(person, kABPersonEmailProperty);
        int emailcount = ABMultiValueGetCount(email);    
        for (int x = 0; x < emailcount; x++)
        {
            //获取email Label
            NSString* emailLabel = (NSString*)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(email, x));
            //获取email值
            NSString* emailContent = (NSString*)ABMultiValueCopyValueAtIndex(email, x);
        }
        //读取地址多值
        ABMultiValueRef address = ABRecordCopyValue(person, kABPersonAddressProperty);
        int count = ABMultiValueGetCount(address);    
        
        for(int j = 0; j < count; j++)
        {
            //获取地址Label
            NSString* addressLabel = (NSString*)ABMultiValueCopyLabelAtIndex(address, j);
            //获取該label下的地址6属性
            NSDictionary* personaddress =(NSDictionary*) ABMultiValueCopyValueAtIndex(address, j);        
            NSString* country = [personaddress valueForKey:(NSString *)kABPersonAddressCountryKey];
            NSString* city = [personaddress valueForKey:(NSString *)kABPersonAddressCityKey];
            NSString* state = [personaddress valueForKey:(NSString *)kABPersonAddressStateKey];
            NSString* street = [personaddress valueForKey:(NSString *)kABPersonAddressStreetKey];
            NSString* zip = [personaddress valueForKey:(NSString *)kABPersonAddressZIPKey];
            NSString* coutntrycode = [personaddress valueForKey:(NSString *)kABPersonAddressCountryCodeKey];
        }
        
        //获取dates多值
        ABMultiValueRef dates = ABRecordCopyValue(person, kABPersonDateProperty);
        int datescount = ABMultiValueGetCount(dates);    
        for (int y = 0; y < datescount; y++)
        {
            //获取dates Label
            NSString* datesLabel = (NSString*)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(dates, y));
            //获取dates值
            NSString* datesContent = (NSString*)ABMultiValueCopyValueAtIndex(dates, y);
        }
        //获取kind值
        CFNumberRef recordType = ABRecordCopyValue(person, kABPersonKindProperty);
        if (recordType == kABPersonKindOrganization) {
            // it's a company
            NSLog(@"it's a company\n");
        } else {
            // it's a person, resource, or room
            NSLog(@"it's a person, resource, or room\n");
        }
        
        
        //获取IM多值
        ABMultiValueRef instantMessage = ABRecordCopyValue(person, kABPersonInstantMessageProperty);
        for (int l = 1; l < ABMultiValueGetCount(instantMessage); l++)
        {
            //获取IM Label
            NSString* instantMessageLabel = (NSString*)ABMultiValueCopyLabelAtIndex(instantMessage, l);
            //获取該label下的2属性
            NSDictionary* instantMessageContent =(NSDictionary*) ABMultiValueCopyValueAtIndex(instantMessage, l);        
            NSString* username = [instantMessageContent valueForKey:(NSString *)kABPersonInstantMessageUsernameKey];
            
            NSString* service = [instantMessageContent valueForKey:(NSString *)kABPersonInstantMessageServiceKey];     
        }
        
        //读取电话多值
        ABMultiValueRef phone = ABRecordCopyValue(person, kABPersonPhoneProperty);
        for (int k = 0; k<ABMultiValueGetCount(phone); k++)
        {
            //获取电话Label
            NSString * personPhoneLabel = (NSString*)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(phone, k));
            //获取該Label下的电话值
            NSString * personPhone = (NSString*)ABMultiValueCopyValueAtIndex(phone, k);
                
        }
        
        //获取URL多值
        ABMultiValueRef url = ABRecordCopyValue(person, kABPersonURLProperty);
        for (int m = 0; m < ABMultiValueGetCount(url); m++)
        {
            //获取电话Label
            NSString * urlLabel = (NSString*)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(url, m));
            //获取該Label下的电话值
            NSString * urlContent = (NSString*)ABMultiValueCopyValueAtIndex(url,m);
        }
        
        //读取照片
        NSData *image = (NSData*)ABPersonCopyImageData(person);
            
    }
}

效果:

2015-04-06 16_30_54.gif

相关文章

  • iOS开发系列--通讯录、蓝牙、内购、GameCenter、iC

    iOS开发系列--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开发汇总http...

  • iOS学习笔记29-系统服务(二)通讯录

    一、通讯录 iOS中的通讯录是存储在数据库中的,由于iOS的权限设计,开发人员是不允许直接访问通讯录数据库的,实现...

  • ios9下vue使用踩坑记录

    问题描述 使用vue开发单页的通讯录选择器组件后。 在iOS 10 和 iOS 8下都正常运行。 就在iOS 9下...

  • iOS13&Xcode11适配问题

    1.通讯录权限问题iOS 13中将禁止应用开发者访问用户通讯录备注信息,需将keys中的CNContactNote...

  • iOS通讯录开发

    场景一:直接选择一个联系人的电话号码 这里不需要先获取所有的联系人自己做联系人列表,直接使用系统自带的Addres...

  • iOS通讯录开发

    今天正好用到通讯录,总结一下使用过程.首先苹果的通讯录是保存在数据库里面的,苹果不允许开发者直接访问数据库.不过可...

  • iOS通讯录开发

    苹果允许访问用户的通讯录,提供的api分为两种,区别在于有没有UI界面,工作中一般都会选用有UI界面,从iOS6开...

  • iOS通讯录开发

    前言 记录下在应用内获取通讯录的相关知识点,涉及到通讯录权限配置,通讯录数据的获取以及数据按首字母排序。 系统通讯...

  • iOS 中简单通讯录列表的使用

    iOS 中简单通讯录列表的使用 最近开发的App有读取用户通讯录的需要,做完这块功能之后顺便整理了一下流程,如下:...

  • iOS9.0之前和之后获取通讯录的方法

    1. iOS 9.0之前获取通讯录的方法 打印结果: 2. iOS 9.0 及 iOS 9.0之后获取通讯录的方法...

网友评论

  • 方圆一里:老铁 被弃用了现在
    方圆一里:@千煌89 [ZXValidateHelper checkTel:phoneNO] 是过滤号码空格的方法吗? 可以提供下吗
    方圆一里:@千煌89 哦哦 刚看到,你可以把新的链接放上去 方便跳转查看:wink:
    千煌89:老铁,新版的我也发过了
  • yaoyao_IOS:怎么判断待添加和待邀请好友呢
    千煌89:@yaomin1224 差不多这个意思吧
    yaoyao_IOS:@千煌89 上传通讯录到服务器么?
    千煌89:跟服务器同步一下
  • 崠崠:有Demo吗
  • 崠崠:作者 如果你的应用应用的范围广、有的用户没有更新,那你的通讯录开发是不是做3个版本之类的,iOS7、8和9之后?
    千煌89:@洪崠崠 最低支持7的话,7之后的也能兼容
  • e5fb1e513efd:有demo吗
  • 咔客:。。我遇到在其他机型上可以获取通讯录 但在真机6splus 上获取不到通讯录。。。这个怎么解决啊
  • 主动性initiative微笑:不错,非常棒!请问这个有iOS10以上的版本吗 ,这个只能在iOS9用啊 iOS 10 会崩溃。
    千煌89:@主动性initiative微笑 请看我的另一篇文章
  • Qiu_W:产品需求:第一次把通讯录告诉服务器之后,以后每次启动app触发某个事件的时候 就把通讯录的增删改查 告诉服务器(不是通讯录的所有数据重新上传) 这个楼主有木有思路
    KevinLwg:你好,请问你这个问题解决了吗?
  • d90b41f4d116:ZXValidateHelper 是用来判断号码的类吗
    千煌89:@大码鞋故事 嗯
  • 那片飘落的树叶:大神,有demo吗
  • 671337ada83e:是获取到了联系人后 relodata,但是数据不刷新,需要点一下tableView或者滑动一下,才会刷新
  • 671337ada83e:大神,有一个问题,为啥进入页面tableVIew加载的这么慢呢,特别慢
    千煌89:@mrshengr 要嘛是线程的问题,要嘛是tableview的问题
  • 33a02bf71691:知道了
  • 33a02bf71691:获取联系人中 备注是怎么获取的呢
  • 5d2a72c8e642:请问楼主 通讯录系统群组 还有收藏是怎么做的?
  • b260f79871c5:能发个demo地址么
  • e763f1ec1cfe:iOS10 用peoplePickerNavigationController的代理方法会报错,可以看下,我解决不了
  • 栈溢出:- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person
    {
    ABPersonViewController *personViewController = [[ABPersonViewController alloc] init];
    personViewController.displayedPerson = person;
    [peoplePicker pushViewController:personViewController animated:YES];
    }
    这个方法一直不进去,这个不是在所有联系人列表点击人调用的么
    千煌89:@栈溢出 你github上写个demo我帮你调试看看吧,这样我也不知道怎么回事呀
    栈溢出:@千煌89 选电话那个能进 点击直接跳转到详情页了
    千煌89:@栈溢出 是的呀,选电话那个能进吗
  • 卜卜星:代码很有帮助就是内存漏了一地....CoreFoundation的对象要记得调用CFRelease()啊
    卜卜星:@千煌89 不会有警告的
    千煌89:@卜卜星 嗯很早就知道了就是文章一直没改,Xcode 里应该都会有警告的
  • 快过年了啊:大神,我用的是场景1的代码,已经实现获取电话号码了,请问怎么拿到姓名啊?在线等。。。
    快过年了啊:@千煌89 已经解决了,非常感谢,楼主真是好人 :kissing_closed_eyes:
    千煌89:@叨客的围脖 ABRecordRef person = CFArrayGetValueAtIndex(people, i);

    NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
    NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
  • 我不是cxk:非常感谢,正好用到
  • feng_dev:大神,电话是多值的,要是想只获取某个标签 比如 住宅 下的电话呢,该则么做?
    还有,电话的数组的读取顺序是和用户 的 添加顺序 有关 还是 和 标签的 默认 顺序 有关?
    千煌89:@枫子哥 直接遍历拿第一个呗……或者生成多个,或者应该用picker而不是直接获取全部通讯录的方式
    feng_dev:@千煌89 现在一般做通讯录开发 不就是 拿到个 名字和电话吗?别的感觉没什么用,因为一般用户也不会填写那么多信息,是吧,我问我几个朋友 添加联系人的时候 ,都是 只写了名字 和电话,

    而且,添加联系人的时候 默认的 电话标签是 住宅 的 ,但是 好像 如果是别人打过来的,在 添加,标签 就变成了 归属地了 比如 什么 天津移动 ,这个标签 是 属于 手机 那个标签 吗?
    获取的时候,我要是 只获取 一个 标签下面的 电话,那个标签没有 ,我怎么才能 换下个标签 来获取,难道 必须 全部遍历 之后 再 获取 想要的那个吗? 我有点纠结
    千煌89:@枫子哥 你打印下住宅的label试试就知道了哇,然后直接拿label取就好了,按照的是添加顺序
  • 蛮荒星域:这里是直接获取通讯录的,应该要告知用户是否获取权限,否则苹果审核不通过
    千煌89:@蛮荒星域 不会啊,你在调用之前会自己弹框请求权限的,不用自己写。只是需要你判断权限状态后提示用户,不提示也没关系的。
  • Jabir_Zhang:long index = ABMultiValueGetIndexForIdentifier(phone,identifier);我这句话在identifier返回=2的时候会奔溃。。。因为index = -1 ,数组一取就奔溃了
    Jabir_Zhang:@eileen01 没有,等大神回复
    eileen01:@Jabir2HLJ 我也遇到了index=-1崩溃的情况,有什么好的解决方案吗?
  • MarkZ:怎么样才能让非号码的label 不相应呢
    千煌89:@MarkZ 等明天摸到电脑了再帮你吧
    MarkZ:@千煌89 就因为不知道怎么去判断的 代码不会写 if(?)
    千煌89:@MarkZ 响应的时候对identifi或者property 加个判断,不是phone就返回
  • MarkZ:楼主 ,第一个调用系统的,如果不点击电话号码,点击邮箱之类的东西电话号码会赋值吗?
    千煌89:@MarkZ 会的,另外我新写了ios9下的通讯录,可以参考下
  • af50ec5b98b7:求demo啊
  • 明明明Y:mark 先按照楼主方法 走一遍! 发现问题求指教
    明明明Y:@千煌89 正在review .. 有问题 我会@你的 谢谢回复!
    千煌89:@明明明Y 什么问题啊……
  • 攻城:求demo 亲
  • coder_feng:demo地址有么
  • NS西北风:楼主,求demo地址》
  • f568ed33cf5b:楼主写得很详细,谢谢!
    coder_feng:@康斯坦丁19111010 有没有例子啊
  • 85172da60b48:删不了评论。。。我想说的是,要release。。。
    85172da60b48:或者用CFBridgingRelease来自动释放
    85172da60b48:@千煌89 https://github.com/PhilCai1993/Contacts/blob/master/contacts/NVMContactManager.m
    CoreFoundation的要手动CFRelease掉~我是看了你的尝试了一下,这个跑几次就内存200多兆了。
    千煌89:@PhilCai 基于arc的啊
  • 85172da60b48:CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);
    CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);

    for ( int i = 0; i < numberOfPeople; i++){
    ABRecordRef person = CFArrayGetValueAtIndex(people, i);
    NSString *firstName = (NSString *)CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
    NSString *lastName = (NSString *)CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
    NSLog(@"%@%@",firstName,lastName);
    NSString *middlename = (NSString*)CFBridgingRelease(ABRecordCopyValue(person, kABPersonMiddleNameProperty));
    NSString *prefix = (NSString*)CFBridgingRelease(ABRecordCopyValue(person, kABPersonPrefixProperty));
    NSString *suffix = (NSString*)CFBridgingRelease(ABRecordCopyValue(person, kABPersonSuffixProperty));
    NSString *nickname = (NSString*)CFBridgingRelease(ABRecordCopyValue(person, kABPersonNicknameProperty));
    NSString *firstnamePhonetic = (NSString*)CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNamePhoneticProperty));
    NSString *lastnamePhonetic = (NSString*)CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNamePhoneticProperty));
    //读取middlename拼音音标
    NSString *middlenamePhonetic = (NSString*)CFBridgingRelease(ABRecordCopyValue(person, kABPersonMiddleNamePhoneticProperty));
    NSString *organization = (NSString*)CFBridgingRelease(ABRecordCopyValue(person, kABPersonOrganizationProperty));
    NSString *jobtitle = (NSString*)CFBridgingRelease(ABRecordCopyValue(person, kABPersonJobTitleProperty));

本文标题:iOS通讯录开发

本文链接:https://www.haomeiwen.com/subject/tlbgxttx.html