通讯录技术

通讯录技术

目标:获取通讯录中的信息.简称AB和CN.

iOS9.0之前:(使用C语言的数据类型)
1. AddressBook
2. AddressBookUI
iOS9.0之后:(使用OC对象来开发)
1. Contact - 没有提供界面,直接操作数据
2. ContactUI - 提供界面

代码:

目标:看的懂,前人写的代码.(了解一下)
  1. 导入AddressBookUI框架
  2. ABPerplePickerNavgationController控制器
  3. 配置代理,注意不能直接设置代理,代理是父类(导航控制器)的代理,他的代理peoplePickerDelegate.
  4. 写代理方法
    已经被废弃了...
// 与UIImagePicker用法类似
    // ABPeoplePickerNavigationController 联系人选择器
    
    // 1. 实例化
    ABPeoplePickerNavigationController *peoplePicker = [[ABPeoplePickerNavigationController alloc] init];
    
    // 2. 配置
    // 配置代理, 通过代理做一些相关的操作
    // delegate 是从 UINavigationController 继承过来的
//    peoplePicker.delegate = self;
    // 注意: 它的代理是peoplePickerDelegate, 而不是delegate
    peoplePicker.peoplePickerDelegate = self;
    
    // 3. 弹出来
    [self presentViewController:peoplePicker animated:YES completion:nil];

/// 代理方法
/**
 选择了某个联系人详情中的具体属性后触发
 * 不能实现选中联系人的代理方法, 否则该方法无效
 */
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
    // person 选中的联系人的记录
    // property 选中的属性的proertyID (哪一种类型)
    // identifier 选中的这一类属性的标识 (判断第一个还是第二个...)
    
    /** 获取选中的电话号码 */
    // 1. 判断类型, 不同类型的处理不一样
    if (property == kABPersonPhoneProperty) {
        // 选中的是一个电话号码
        ABMultiValueRef multiPhone = ABRecordCopyValue(person, kABPersonPhoneProperty);
        
        // 判断选中的是哪一个电话号码
        NSLog(@"%zd", identifier);
        
        CFIndex index = ABMultiValueGetIndexForIdentifier(multiPhone, identifier);
        CFStringRef phone = ABMultiValueCopyValueAtIndex(multiPhone, index);
        
        NSString *phoneString = CFBridgingRelease(phone);
        NSLog(@"%@", phoneString);
    }
}

注意一种类型以Ref结尾,说明是C语言数据类型.
CF:Core Foundtation框架,是不支持ARC的,这就是为什么碰到Creat,Copy就会产生内存泄漏,需要手动释放内存.

重点: Foundation和Core Foundataion 之间的转化

  1. 转化方式1:直接转化,对象所有权(谁负责生命周期管理)不会改变,还是C的生命周期.
    __bridge
    所以需要CFRelease()一下.

  2. 转化方式2:CFBridgingRelease(),等价于(__bridge_transer id)会转化对象的所有权,由ARC(编译期特性)负责.

OC的重点掌握
  1. 导入ContactUI框架
  2. CNContactPickerViewController
  3. 配置代理.
  4. 弹出控制器.

代理方法:

  1. 点击右上角取消按钮
  2. 选中了联系人
    1. 联系人具体信息
    2. 电话号码:多个电话号码,CNLabledValue:类似于字典.
  3. 选中多个联系人,选中单个的方法就不走了(类似2中的方法)
  4. 选中联系人属性
    4.1. 通用的代理方法,需要判断类型.如果是这个你需要的类型才作出处理.
    4.2. 判断选中的类型是否是电话号码.找到相关value,输出电话号码.
  5. 加一个属性,指定只显示的属性display...
代码部分
// 1. 实例化一个联系人选择器
    CNContactPickerViewController *picker= [[CNContactPickerViewController alloc] init];
    
    // 2. 配置
    picker.delegate = self;
    
    // 3. 弹出来
    [self presentViewController:picker animated:YES completion:nil];

/**
 选中了某个联系人后触发
 @param contact 选中的联系人信息
 */
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact
{
    // CNContact : 表示联系人的具体信息
    NSLog(@"%@, %@", contact.familyName, contact.givenName);
    
    // CNLabeledValue : 类似于字典, 保存了 mobile : 5555-1212
    NSArray <CNLabeledValue *> *phoneNumbers = contact.phoneNumbers;
    for (CNLabeledValue *labelValue in phoneNumbers) {
        // CNPhoneNumber 表示电话号码
        CNPhoneNumber *number = labelValue.value;
        NSLog(@"%@, %@", labelValue.label, number.stringValue);
    }
}

/**
 实现该代理方法, 支持多选, 选中单个联系人的代理方法失效
 */
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContacts:(NSArray<CNContact*> *)contacts
{
    for (CNContact *contact in contacts) {
        NSLog(@"%@, %@", contact.familyName, contact.givenName);
    }
}

/**
 在联系人详情界面中选了联系人的某个属性
 @param contactProperty 选中的联系的某个属性
 */
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty
{
    // CNContactProperty : 表示联系人的某一个属性
    
    // ========== 获取选中的电话号码 ==========
    NSLog(@"%@", contactProperty);
    
    // 1. 判断选中的类型是否为电话号码
    // CNContactPhoneNumbersKey的内容就是@"phoneNumbers"
    if ([contactProperty.key isEqualToString:@"phoneNumbers"]) {
        NSLog(@"%@", contactProperty.value);
        
        CNPhoneNumber *number = contactProperty.value;
        NSLog(@"%@", number.stringValue);
    }
    
    // ========== 获取选中的邮箱 ==========
    if ([contactProperty.key isEqualToString:CNContactEmailAddressesKey]) {
        // 就是NSString类型
        NSLog(@"%@", contactProperty.value);
    }
}

目标:获取通讯录中,所有联系人信息.

相关框架:Contacts框架

核心类:CNContactStore.作用:可以检索和保存联系人等信息

思路:

  1. 获取通讯录信息
    1.1. 首先获取授权权限(参照地图)
    1.1.1. 获取当前授权状态
    1.1.2. 判断授权状态是否做出改变处理
    1.1.3. 请求授权.
  2. 遍历通讯录中所有联系人信息.
  3. 遍历获取电话号码对应的类型.

注意问题:

  1. 权限问题配置info.plist(产生崩溃)
  2. 在检索中没有使用fetch.产生崩溃.(没听清,用到时处理一下)
// ========== 通讯录的授权处理 ==========
    // 1. 获取当前的授权状态
    CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
    
    // 2. 判断是否已经做出决定
    if (status == CNAuthorizationStatusNotDetermined) {
        [self.contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
            
            // 授权状态的结果, 直接通过Block回调
            if (error) {
                // 相关的错误信息, 在CNError.h文件当中
                NSLog(@"%@", error);
                return;
            }
            
            if (granted == YES) {
                NSLog(@"授权成功");
            }
        }];
    }
    
    // ========== 获取通讯录当中联系人电话和姓名 ==========
    // 直接遍历通讯录中所有联系人的信息
    
    // CNContactFetchRequest : 联系人信息(如电话, 邮箱, 地址等)的`检索请求`
    // 创建了一个检索请求, 要检索的信息包括姓名, 电话
    CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey]];
    
    NSError *error = nil;
    // 遍历所有的联系人信息, 如果成功返回YES, 每个联系人信息都会执行一次Block
    BOOL result = [self.contactStore enumerateContactsWithFetchRequest:request error:&error usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
        
        // CNContact : 检索到的每个联系人的所有信息
        // NSLog(@"%@", contact.emailAddresses);
        // stop指针能在需要的时候停止遍历
        
        // 获取姓名
        NSLog(@"%@, %@", contact.familyName, contact.givenName);
        // 获取电话号码
        NSArray <CNLabeledValue *> *phonenumbers = contact.phoneNumbers;
        for (CNLabeledValue *labeledValue in phonenumbers) {
            // 获取到电话号码对应的类型
            CNPhoneNumber *number = labeledValue.value;
            NSLog(@"%@, %@", labeledValue.label, number.stringValue);
        }
    }];
    
    // 失败处理
    if (result == NO && error) {
        NSLog(@"获取所有联系人信息失败: %@", error);
    }

了解知识:AddressBook,访问通讯录数据
ABAddressBookRef:通讯录
CFArrayRef:联系人数组

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,386评论 25 707
  • 如何访问用户的通讯录 在iOS中,有2个框架可以访问用户的通讯录 AddressBookUI.framework ...
    JonesCxy阅读 751评论 0 2
  • 亲爱的,请爱你自己,高傲的像个女王 马克思曾说,唯有爱情和咳嗽无法掩饰。一个人如果真的爱你,心里装的都是你,他总是...
    易郎阅读 944评论 0 2
  • 张东辉,焦点初级第43期坚持原创分享第80天(2017.11.20) 今天是周一,从一大早到现在都在工作,刚刚坐下...
    星悦传奇阅读 314评论 0 0
  • 打滴滴从唐河一中赶往南阳市二中,花费42.5元,顾雇建航开车从南阳到镇平一来回一共150元,今天三十号,打车火车站...
    三河散人阅读 132评论 0 0