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

    相关文章

      网友评论

      • 方圆一里:老铁 被弃用了现在
        方圆一里:@千煌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