1、读取通信录

  1)、9.0以前:AddressBook

  2)、9.0以后:Contacts

2、调用通信录UI(不弄)

  1)、9.0以前:AddressBookUI

  2)、9.0以后:ContactsUI

3、参考

0、写在前面

  1)、plist 需要设置 隐私权限描述

    NSContactsUsageDescription(Privacy - Contacts Usage Description) :请求访问通讯录(自定义)

  2)、一般应用只需要电话就够了,不过,如果想做 坏事 大数据分析,可能还是要全读取给后台吧?

  3)、9.0后的 Contacts 类:

    3-1)、如果请求数据的数组里没有该Key,但在 block 判断有,会奔溃。

    3-2)、请求类型key,有10.0后的,需要注意,做判断。               

  4)、原生UI不打算弄了,感觉一般都是自定义UI,比如:有注册的在上面,添加好友按钮,没注册的在下面,邀请好友按钮。

  5)、有空再整理成 单例manage。

1、读取通信录

  1)、9.0以前

    1-1)、头文件

#import <AddressBook/AddressBook.h>

    1-2)、判断是否有权限

- (void)DetermineAndReadAddressBook
{
// 判断是否授权
ABAuthorizationStatus authorizationStatus = ABAddressBookGetAuthorizationStatus();
if (authorizationStatus == kABAuthorizationStatusNotDetermined) {
// 请求授权
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error){
if (granted) {
// 授权成功
[self readAddressBook];
} else {
// 授权失败
NSLog(@"提示:用户取消授权,读取失败");
}
});
}
else if (authorizationStatus == kABAuthorizationStatusAuthorized){
// 授权过
[self readAddressBook];
}
else {
dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面
NSLog(@"提示:应用-通信录 设置");
});
}
}

    1-3)、读取并保存模型(未做)

- (void)readAddressBook {

    // 获取所有联系人
ABAddressBookRef addressBookRef = ABAddressBookCreate();
// 获取所有联系人 数据
CFArrayRef peoples = ABAddressBookCopyArrayOfAllPeople(addressBookRef);
// 获取所有联系人 个数
CFIndex peoplesCount = ABAddressBookGetPersonCount(addressBookRef); for (int i = 0; i < peoplesCount; i++) {
//获取联系人对象的引用
ABRecordRef people = CFArrayGetValueAtIndex(peoples, i); //获取当前联系人名字
NSString *firstName=(__bridge NSString *)(ABRecordCopyValue(people, kABPersonFirstNameProperty));
//获取当前联系人姓氏
NSString *lastName=(__bridge NSString *)(ABRecordCopyValue(people, kABPersonLastNameProperty));
NSLog(@"--------------------------------------------------");
NSLog(@"firstName=%@, lastName=%@", firstName, lastName); //获取当前联系人中间名
NSString *middleName=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonMiddleNameProperty));
//获取当前联系人的名字前缀
NSString *prefix=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonPrefixProperty));
//获取当前联系人的名字后缀
NSString *suffix=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonSuffixProperty));
//获取当前联系人的昵称
NSString *nickName=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonNicknameProperty));
//获取当前联系人的名字拼音
NSString *firstNamePhoneic=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonFirstNamePhoneticProperty));
//获取当前联系人的姓氏拼音
NSString *lastNamePhoneic=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonLastNamePhoneticProperty));
//获取当前联系人的中间名拼音
NSString *middleNamePhoneic=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonMiddleNamePhoneticProperty));
//获取当前联系人的公司
NSString *organization=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonOrganizationProperty));
//获取当前联系人的职位
NSString *job=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonJobTitleProperty));
//获取当前联系人的部门
NSString *department=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonDepartmentProperty)); //获取当前联系人的生日
NSDate *birthday=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonBirthdayProperty));
//获取当前联系人的备注
NSString *notes=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonNoteProperty)); //获取当前联系人头像图片
NSData *userImage=(__bridge NSData*)(ABPersonCopyImageData(people)); //获取kind值
CFNumberRef kindType = ABRecordCopyValue(people, kABPersonKindProperty);
if (kindType == kABPersonKindOrganization) {
NSLog(@"公司");
} else {
// it's a person, resource, or room
NSLog(@"个人");
} //获取创建当前联系人的时间 注意是NSDate
NSDate *creatTime=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonCreationDateProperty));
//获取最近修改当前联系人的时间
NSDate *alterTime=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonModificationDateProperty)); //获取当前联系人的电话 数组
NSMutableArray *phoneArray = [[NSMutableArray alloc]init];
ABMultiValueRef phones = ABRecordCopyValue(people, kABPersonPhoneProperty);
CFIndex phonesCount = ABMultiValueGetCount(phones);
for (NSInteger j=0; j<phonesCount; j++) {
//获取电话Label
NSString *phoneLabel = (__bridge NSString*)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(phones, j));
//获取該Label下的电话值
NSString *phone = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(phones, j));
NSLog(@"phone=%@", phone);
[phoneArray addObject:phone];
} //获取IM多值
NSMutableArray *instantMessageArray = [[NSMutableArray alloc]init];
ABMultiValueRef instantMessages = ABRecordCopyValue(people, kABPersonInstantMessageProperty);
CFIndex instantMessagesCount = ABMultiValueGetCount(instantMessages);
for (int j = 1; j < instantMessagesCount; j++)
{
//获取IM Label
NSString* instantMessageLabel = (__bridge NSString*)ABMultiValueCopyLabelAtIndex(instantMessages, j);
//获取IM 的内容
NSDictionary* instantMessageContent =(__bridge NSDictionary*)ABMultiValueCopyValueAtIndex(instantMessages, j);
NSString* username = [instantMessageContent valueForKey:(NSString *)kABPersonInstantMessageUsernameKey];
NSString* service = [instantMessageContent valueForKey:(NSString *)kABPersonInstantMessageServiceKey];
} //获取URL多值
NSMutableArray *urlArray = [[NSMutableArray alloc]init];
ABMultiValueRef urls = ABRecordCopyValue(people, kABPersonURLProperty);
CFIndex urlsCount = ABMultiValueGetCount(urls);
for (int j = 0; j < urlsCount; j++)
{
//获取电话Label
NSString * urlLabel = (__bridge NSString*)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(urls, j));
//获取該Label下的电话值
NSString * urlContent = (__bridge NSString*)ABMultiValueCopyValueAtIndex(urls,j);
} //获取当前联系人的邮箱 注意是数组
NSMutableArray *emailArray = [[NSMutableArray alloc]init];
ABMultiValueRef emails= ABRecordCopyValue(people, kABPersonEmailProperty);
CFIndex emailsCount = ABMultiValueGetCount(emails);
for (NSInteger j=0; j< emailsCount; j++) {
//获取email Label
NSString* emailLabel = (__bridge NSString*)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(emails, j));
//获取email值
NSString *email = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(emails, j));
NSLog(@"email=%@", email);
[emailArray addObject:email];
} //获取地址 注意是数组
NSMutableArray *addressArray = [[NSMutableArray alloc]init];
ABMultiValueRef addresss = ABRecordCopyValue(people, kABPersonAddressProperty);
CFIndex addresssCount = ABMultiValueGetCount(addresss);
for (int j=0; j<addresssCount; j++) {
// 地址类型
NSString *addressLabel = (__bridge NSString *)(ABMultiValueCopyLabelAtIndex(addresss, j));
NSDictionary * personaddress = (__bridge NSDictionary *)(ABMultiValueCopyValueAtIndex(addresss, j));
// 获取地址
NSString* country = [personaddress valueForKey:(NSString *)kABPersonAddressCountryKey];
NSString* state = [personaddress valueForKey:(NSString *)kABPersonAddressStateKey];
NSString* city = [personaddress valueForKey:(NSString *)kABPersonAddressCityKey];
NSString* street = [personaddress valueForKey:(NSString *)kABPersonAddressStreetKey];
NSString* zip = [personaddress valueForKey:(NSString *)kABPersonAddressZIPKey];
NSString* coutntrycode = [personaddress valueForKey:(NSString *)kABPersonAddressCountryCodeKey];
//地址字符串,可以按需求格式化
NSString *adress = [NSString stringWithFormat:@"国家:%@\n省:%@\n市:%@\n街道:%@\n邮编:%@",country,state,city,street,zip];
} //获取当前联系人纪念日
NSMutableArray *dateArr = [[NSMutableArray alloc]init];
ABMultiValueRef dates= ABRecordCopyValue(people, kABPersonDateProperty);
CFIndex datesCount = ABMultiValueGetCount(dates);
for (NSInteger j=0; j<datesCount; j++) {
//获取dates Label
NSString* dateLabel = (__bridge NSString*)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(dates, j));
//获取纪念日日期
NSDate *date =(__bridge NSDate*)(ABMultiValueCopyValueAtIndex(dates, j));
//获取纪念日名称
NSString *str =(__bridge NSString*)(ABMultiValueCopyLabelAtIndex(dates, j));
NSDictionary *tempDic = [NSDictionary dictionaryWithObject:date forKey:str];
[dateArr addObject:tempDic];
}
}
}

  2)、9.0以后

    2-1)、头文件

#import <Contacts/Contacts.h>

    2-2)、判断是否有权限

- (void)DetermineAndReadAddressBook
{
// 判断是否授权
CNAuthorizationStatus authorizationStatus = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]; if (authorizationStatus == CNAuthorizationStatusNotDetermined) {
CNContactStore *contactStore = [[CNContactStore alloc] init];
[contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
// 授权成功
[self readAddressBook];
} else {
// 授权失败
NSLog(@"提示:用户取消授权,读取失败");
}
}];
}
else if (authorizationStatus == CNAuthorizationStatusAuthorized){
// 授权过
[self readAddressBook];
}
else {
dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面
NSLog(@"提示:应用-通信录 设置");
});
}
}

    2-3)、读取并保存模型(未做)

- (void)readAddressBook {
// 获取指定的字段,如果这里不列出,在下面block读取,会奔溃。注意,有一个是10.0以后的。
NSArray *keysToFetch = @[CNContactNamePrefixKey,
CNContactGivenNameKey,
CNContactMiddleNameKey,
CNContactFamilyNameKey,
CNContactPreviousFamilyNameKey,
CNContactNameSuffixKey,
CNContactNicknameKey,
CNContactOrganizationNameKey,
CNContactDepartmentNameKey,
CNContactJobTitleKey,
CNContactPhoneticGivenNameKey,
CNContactPhoneticMiddleNameKey,
CNContactPhoneticFamilyNameKey,
CNContactPhoneticOrganizationNameKey, // 10.0
CNContactBirthdayKey,
CNContactNonGregorianBirthdayKey,
CNContactNoteKey,
CNContactImageDataKey,
CNContactThumbnailImageDataKey,
CNContactImageDataAvailableKey,
CNContactTypeKey,
CNContactPhoneNumbersKey,
CNContactEmailAddressesKey,
CNContactPostalAddressesKey,
CNContactDatesKey,
CNContactUrlAddressesKey,
CNContactRelationsKey,
CNContactSocialProfilesKey,
CNContactInstantMessageAddressesKey]; CNContactFetchRequest *fetchRequest = [[CNContactFetchRequest alloc] initWithKeysToFetch:keysToFetch];
CNContactStore *contactStore = [[CNContactStore alloc] init];
[contactStore enumerateContactsWithFetchRequest:fetchRequest error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) { // 获取名字
NSString *givenName = contact.givenName;
NSString *familyName = contact.familyName;
NSLog(@"-------------------------------------------------------");
NSLog(@"givenName=%@, familyName=%@", givenName, familyName); // 获取电话
NSArray *phoneNumbers = contact.phoneNumbers;
for (CNLabeledValue *labelValue in phoneNumbers) {
NSString *label = labelValue.label;
CNPhoneNumber *phoneNumber = labelValue.value; NSLog(@"label=%@, phone=%@", label, phoneNumber.stringValue);
} // 获取对方IM
NSArray *ims = contact.instantMessageAddresses;
for (CNLabeledValue *labelValue in ims) {
NSString *label = labelValue.label;
CNInstantMessageAddress *adds = labelValue.value; NSLog(@"label=%@, add.username=%@,add.service=%@", label, adds.username , adds.service);
} // *stop = YES; // 停止循环,相当于break;
}];
}

  

3、参考

《iOS的通讯录开发》         --千煌89    简书

《iOS 获取通讯录的4种方式详解》   --vbirdbest   CSDN

iOS:通信录(完成)(18-01-18更)的更多相关文章

  1. Wed Jul 04 18:01:38 CST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended

    Wed Jul 04 18:01:38 CST 2018 WARN: Establishing SSL connection without server's identity verificatio ...

  2. 非智能手机通信录备份并还原至Android智能手机方法

    随着智能手机早已深入普通用户的生活,2-3线城市的用户也逐渐从使用非智能机换成使用智能机.最近便遇见了这样一个转移通讯录的需求.之前使用的手机型号是BBK K201,通信录中绝大部分保存在了手机中,最 ...

  3. 实现iOS图片等资源文件的热更新化(三):动态的资源文件夹

    简介 此文,将尝试动态从某个不确定的文件夹中加载资源文件.文章,会继续完善自定义的 imageNamed 函数,并为下一篇文章铺垫. 这么做的意义 正如我们经常所说的那样,大多数情景知道做事的意义往往 ...

  4. 实现iOS图片等资源文件的热更新化(五): 一个简单完整的资源热更新页面

    简介 一个简单的关于页面,有一个图片,版本号,App名称等,着重演示各个系列的文章完整集成示例. 动机与意义 这是系列文章的最后一篇.今天抽空写下,收下尾.文章本身会在第四篇的基础上,简单扩充下代码, ...

  5. 实现iOS图片等资源文件的热更新化(零): 序

    必要的序 以后在写系列文章,准备把基本的规划和动机等,单独作为一个小的序言部分给独立出来.序言部分,可以较为完整地交待系列文章的写作动机,所展示的编码技术可能的应用场景等.个人,我还是比较看重文章或者 ...

  6. iOS开发Swift篇(01) 变量&常量&元组

    iOS开发Swift篇(01) 变量&常量&元组 说明: 1)终于要写一写swift了.其实早在14年就已经写了swift的部分博客,无奈时过境迁,此时早已不同往昔了.另外,对于14年 ...

  7. (五)backbone - DEMO - 通信录改造之使用requirejs

    DEMO介绍是 DEMO通信录的扩展,使用requirejs模块化整合 大体实现 • model文件 model/contact.js define(function (){ // user cont ...

  8. 管理Android通信录

    Android提供了Contacts应用程序来管理联系人,并且Android系统还为联系人管理提供了ContentProvider,这就同意其他应用程序以ContentResolver来管理联系人数据 ...

  9. 通信录列表+复杂Adapter分析

    概述 最近写论文之余玩起了github,发现有个citypicker挺不错的,高仿了美团城市选择和定位的一些功能 地址链接 效果图如下: 自己手动写了一遍优化了一些内容,学到了一些姿势,下面对其中一些 ...

随机推荐

  1. Android LinkedList和ArrayList的区别

    LinkedeList和ArrayList都实现了List接口,但是它们的工作原理却不一样.它们之间最主要的区别在于ArrayList是可改变大小的数组,而LinkedList是双向链接串列(doub ...

  2. 线性表的Java实现--链式存储(单向链表)

    单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始. 链式存储结构的线性表将采用一组任意的存储单元存放线性表中的数据元素.由于不需要按顺序存储,链表在 ...

  3. 如何用kindle看论文

    kindle的pdf显示效果向来不好,那么如何把pdf转换成mobi格式呢 可以把个人文件(pdf)发送至您的[发送至Kindle]电子邮箱时,在电子邮件的主题栏中填写"convert&qu ...

  4. Perl常用语法

    本文主要为了方便阅读.编写perl脚本而记录的常用的命令.语法. 一.条件判断语法 注意,数字 0, 字符串 '0' . "" , 空 list () , 和 undef 为 fa ...

  5. asp.net session 保存实体类对象

    存:User user=new User();session["USER"]=user; 取:User u= (User ) session["USER"];

  6. MFC连接Mysql数据库执行查询和插入

    配置环境: include:mysql.h文件 lib:libmysql.lib文件 dll::libmysql.dll文件 连接代码: MYSQL m_sqlCon; MYSQL_RES *m_re ...

  7. Python学习---线程/协程/进程学习 1220【all】

    Python学习---线程基础学习 Python学习---线程锁/信号量/条件变量同步1221 Python学习---同步条件event/队列queue1223 Python学习---进程 1225 ...

  8. 3.5星|《刷屏:视频时代的风传法则》:YouTube热门视频回顾与分析

    刷屏:视频时代的疯传法则 作者2010年加入YouTube.本书是作者对YouTube上的热门视频的回顾与分析.第2-9章各讲一个类别的热门视频:恶搞.混音.网络歌曲.广告.现场目击.知识与科技.小众 ...

  9. codeforces 12D Ball

    codeforces 12D Ball 这道题有两种做法 一种用树状数组/线段树维护区间最值,一种用map维护折线,昨天我刚遇见了一道类似的用STL维护折线的题目: 392D Three Arrays ...

  10. codeforces 808G Anthem of Berland

    codeforces 808G Anthem of Berland 题面 给定\(s\)串和\(t\)串,字符集是小写字母.\(s\)串中有些位置的值不确定,要求你确定这些位置上的值,使得\(t\)在 ...