Demo地址:我的github仓库

啦啦啦,一天一更新博客的节奏啊,前天晚上研究滴滴出行APP,发现它有一个紧急联系人的功能诶!!!

宝宝仔细的研究了一下,发现弹出联系人的控制器(CNContactPickerViewController)之后当选择一个联系人之后,

滴滴上就出现了我选择的那个联系人的名字诶!!!

跟我存储联系人的名字一模一样!!!

由此进行了一番研究,于昨晚在浩如烟海的博客中找到了这篇比较详细的博客与大家分享,其中做了一些修改。

/*******************分割线*********************/

一、引言

在以前iOS开发中,涉及联系人相关的编程,代码都非常繁琐,并且框架的设计也不是Objective-C风格的,这使开发者用起来非常的难受。在iOS9中,apple终于解决了这个问题,全新的Contacts Framework将完全替代AddressBookFramework,AddressBookFramework也将成为历史被弃用。至于AddressBookFramework的相关api如何繁琐,在以前的博客中有记录,地址如下:

联系人信息相关编程:http://my.oschina.net/u/2340880/blog/407347。

联系人UI界面相关编程:http://my.oschina.net/u/2340880/blog/407973。

这一新的框架是iOS9新特性中十分受欢迎的一个。apple的Objective—C体系也更加完善与强大。

二、让我们来添加一个联系人

新的框架的整体思路是通过配置与请求来管理联系人,这样做有一个非常大的好处,逻辑简单,代码层次清晰。如下,通过添加一个联系人来向大家做演示:

1、联系人对象:CNContact

这个对象是用来配置联系人信息的,有可变的CNMutaleContact和CNContact,区别用来读取和创建联系人。CNContact对象中有许多属性,对应联系人的一些信息。

首先,创建CNMutableContact对象:

 CNMutableContact * contact = [[CNMutableContact alloc]init];

设置联系人头像:

contact.imageData = UIImagePNGRepresentation([UIImage imageNamed:@"Icon.png"]);

设置联系人姓名:

  //设置名字contact.givenName = @"Yanhua";//设置姓氏contact.familyName = @"Wong";

设置联系人邮箱:

CNLabeledValue *homeEmail = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:@"emywong@sina.com"];CNLabeledValue *workEmail =[CNLabeledValue labeledValueWithLabel:CNLabelWork value:@"wangyanhua@d*****y.com.cn"];contact.emailAddresses = @[homeEmail,workEmail];

这里需要注意,emailAddresses属性是一个数组,数组中是才CNLabeledValue对象,CNLabeledValue对象主要用于创建一些联系人属性的键值对应,通过这些对应,系统会帮我们进行数据的格式化,例如CNLabelHome,就会将号码格式成家庭邮箱的格式,相应的其他键如下:

//家庭
CONTACTS_EXTERN NSString * const CNLabelHome                             NS_AVAILABLE(10_11, 9_0);
//工作
CONTACTS_EXTERN NSString * const CNLabelWork                             NS_AVAILABLE(10_11, 9_0);
//其他
CONTACTS_EXTERN NSString * const CNLabelOther                            NS_AVAILABLE(10_11, 9_0);// 邮箱地址
CONTACTS_EXTERN NSString * const CNLabelEmailiCloud                      NS_AVAILABLE(10_11, 9_0);// url地址
CONTACTS_EXTERN NSString * const CNLabelURLAddressHomePage               NS_AVAILABLE(10_11, 9_0);// 日期
CONTACTS_EXTERN NSString * const CNLabelDateAnniversary                  NS_AVAILABLE(10_11, 9_0);

设置联系人电话:

contact.phoneNumbers = @[[CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberiPhone value:[CNPhoneNumber phoneNumberWithStringValue:@"***********"]]];

联系人电话的配置方式和邮箱类似,键值如下:

CONTACTS_EXTERN NSString * const CNLabelPhoneNumberiPhone                NS_AVAILABLE(10_11, 9_0);
CONTACTS_EXTERN NSString * const CNLabelPhoneNumberMobile                NS_AVAILABLE(10_11, 9_0);
CONTACTS_EXTERN NSString * const CNLabelPhoneNumberMain                  NS_AVAILABLE(10_11, 9_0);
CONTACTS_EXTERN NSString * const CNLabelPhoneNumberHomeFax               NS_AVAILABLE(10_11, 9_0);
CONTACTS_EXTERN NSString * const CNLabelPhoneNumberWorkFax               NS_AVAILABLE(10_11, 9_0);
CONTACTS_EXTERN NSString * const CNLabelPhoneNumberOtherFax              NS_AVAILABLE(10_11, 9_0);
CONTACTS_EXTERN NSString * const CNLabelPhoneNumberPager                 NS_AVAILABLE(10_11, 9_0);

这里的CNPhoneNumber对象也是iOS9中的一个新的类,专门用来创建电话号码,之中方法如下:

@interface CNPhoneNumber : NSObject <NSCopying, NSSecureCoding>//通过类方法创建
+ (instancetype)phoneNumberWithStringValue:(NSString *)stringValue;
//通过初始化方法创建
- (instancetype)initWithStringValue:(NSString *)string;@property (readonly, copy, NS_NONATOMIC_IOSONLY) NSString *stringValue;@end

设置联系人地址:

  CNMutablePostalAddress * homeAdress = [[CNMutablePostalAddress alloc]init];homeAdress.street = @"某街道";homeAdress.city = @"威海市";homeAdress.state = @"山东省"; homeAdress.country = @"中国";  homeAdress.postalCode = @"221B";contact.postalAddresses = @[[CNLabeledValue labeledValueWithLabel:CNLabelHome value:homeAdress]];

设置生日:

NSDateComponents * birthday = [[NSDateComponents  alloc]init];birthday.day=5;birthday.month=2;birthday.year=1995;contact.birthday=birthday;

2、创建添加联系人请求:CNSaveRequest

CNSaveRequest是用于存储联系人的请求类,通过这个类,我们可以创建批量添加、修改或者删除联系人的请求,例如添加上面我们创建的联系人对象:

   //初始化方法CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];//添加联系人[saveRequest addContact:contact toContainerWithIdentifier:nil];

这个类中还有许多方便我们操作的方法:

@interface CNSaveRequest : NSObject
//添加一个联系人
- (void)addContact:(CNMutableContact *)contact toContainerWithIdentifier:(nullable NSString *)identifier;//更新一个联系人
- (void)updateContact:(CNMutableContact *)contact;
//删除一个联系人
- (void)deleteContact:(CNMutableContact *)contact;
//添加一组联系人
- (void)addGroup:(CNMutableGroup *)group toContainerWithIdentifier:(nullable NSString *)identifier;
//更新一组联系人
- (void)updateGroup:(CNMutableGroup *)group;
//删除一组联系人
- (void)deleteGroup:(CNMutableGroup *)group;
//向组中添加子组
- (void)addSubgroup:(CNGroup *)subgroup toGroup:(CNGroup *)group NS_AVAILABLE(10_11, NA);
//在组中删除子组
- (void)removeSubgroup:(CNGroup *)subgroup fromGroup:(CNGroup *)group NS_AVAILABLE(10_11, NA);
//向组中添加成员
- (void)addMember:(CNContact *)contact toGroup:(CNGroup *)group;
//向组中移除成员
- (void)removeMember:(CNContact *)contact fromGroup:(CNGroup *)group;@end

3、进行联系人的写入操作:CNContactStore

CNContactStore是一个用于存取联系人的上下文桥梁,现在,把我们创建的添加联系人的请求写入:

    CNContactStore * store = [[CNContactStore alloc]init];[store executeSaveRequest:saveRequest error:nil];

在模拟器上运行程序,打开联系人,效果如下:

联系人界面:

联系人详情:

三、获取格式化的联系人信息

iOS9中,ContactFramework也为开发者提供了非常方便的格式化信息的方法,还拿我们上面创建的联系人对象举例:

1、获取格式化的联系人姓名

NSString * foematter =[CNContactFormatter stringFromContact:contact style:CNContactFormatterStyleFullName];NSLog(@"%@",foematter);

这个运行后会打印出jaki zhang,其中style风格枚举如下:

typedef NS_ENUM(NSInteger, CNContactFormatterStyle)
{//获取全名CNContactFormatterStyleFullName,//获取拼音全名CNContactFormatterStylePhoneticFullName,
} NS_ENUM_AVAILABLE(10_11, 9_0);

2、获取格式化的联系人地址

 NSString * foematter =[CNPostalAddressFormatter stringFromPostalAddress:homeAdress style:CNPostalAddressFormatterStyleMailingAddress];NSLog(@"%@",foematter);

打印如下:

四、提取联系人

在开发中,提取联系人的使用率要远远高于创建联系人,ContactFramework提取联系人的方式,类似于数据库的检索方式,通过配置条件,提取出我们需要的数据,例如:

CNContactStore * stroe = [[CNContactStore alloc]init];//检索条件,检索所有名字中有WO的联系人NSPredicate * predicate = [CNContact predicateForContactsMatchingName:@"wong"];//提取数据NSArray * contacts = [stroe unifiedContactsMatchingPredicate:predicate keysToFetch:@[CNContactGivenNameKey] error:nil];

keysToFetch是设置提取联系人的哪些数据,如上则只提取出检索联系人的名字。

同样,也可以通过请求的方式来对联系人进行遍历:

    CNContactStore * stroe = [[CNContactStore alloc]init];CNContactFetchRequest * request = [[CNContactFetchRequest alloc]initWithKeysToFetch:@[CNContactPhoneticFamilyNameKey]];[stroe enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {NSLog(@"%@",contact);}];

五、ContactFramework UI相关

iOS9中,系统也为我们封装好了一套联系人的UI界面,用起来也十分方便,主要新增的controller有两个:

CNContactPickerViewController:展示联系人列表的controller

CNContactViewController:展示联系人详细信息的controller

示例如下:

弹出联系人列表:

 CNContactPickerViewController * con = [[CNContactPickerViewController alloc]init];[self presentViewController:con animated:YES completion:nil];

效果如下:

联系人逻辑的相关处理主要在CNContactPickerDelegate中完成:

//视图取消时 调用的方法
- (void)contactPickerDidCancel:(CNContactPickerViewController *)picker;
//选中与取消选中时调用的方法
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact;
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty;
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContacts:(NSArray<CNContact*> *)contacts;
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperties:(NSArray<CNContactProperty*> *)contactProperties;

CNContactViewController则是用来显示具体联系人的详细信息的,比如:

    CNContactViewController * con = [CNContactViewController viewControllerForContact:contact];[self presentViewController:con animated:YES completion:nil];

相关代理回调函数如下:

//将要展示联系人信息与已经展示联系人信息的回调
- (BOOL)contactViewController:(CNContactViewController *)viewController shouldPerformDefaultActionForContactProperty:(CNContactProperty *)property;
- (void)contactViewController:(CNContactViewController *)viewController didCompleteWithContact:(nullable CNContact *)contact;

iOS 全新的联系人与联系人UI框架相关推荐

  1. iOS微信QQ聊天界面的UI框架以及Socket简单实现群聊功能

    7.1日更新 Python3 TCP Demo相关 https://blog.csdn.net/Deft_MKJing/article/details/80851879 2.2日更新,socket简易 ...

  2. iOS之UI--主流框架的搭建-- 仿制QQ的UI框架

    iOS之UI--主流框架的搭建-- 仿制QQ的UI框架 使用XCode搭建多个控制器界面,一般在实际开发中建议超过四个控制器界面使用纯代码. 下面的实例其实已经超过了四个,总结详细步骤的目的,主要是更 ...

  3. WWDC19 苹果宣布全新 UI 框架 SwiftUI

    2019 年 WWDC 大会上,苹果在压轴环节向大众宣布了基于 Swift 语言构建的全新 UI 框架 -- SwiftUI.开发者可通过它快速为所有的 Apple 平台创建美观.动态的应用程序. 在 ...

  4. iOS 9人机界面指南(一):UI设计基础

    [ISUX译]iOS 9人机界面指南(一):UI设计基础 raina2015.10.29 文章索引 1.1 为iOS而设计(Designing for iOS) 1.1.1 设计跟随内容 (Defer ...

  5. Android 开源UI框架汇总

    1. github排名 https://github.com/trending,github搜索:https://github.com/search 2.https://github.com/wasa ...

  6. iOS 9人机界面指南(四):UI元素

    iOS 9人机界面指南(四):UI元素 2016-02-14 11:51  编辑: suiling  分类:产品设计  来源:腾讯ISUX 0  31 iOS 9人机界面指南苹果文档 java高级软件 ...

  7. Google跨平台UI框架 Flutter beta 重磅发布,这里有你需要了解的一切

    2018年2月27日,在西班牙巴塞罗那世界移动大会上,Google发布 Flutter 的第一个 beta 版本.Flutter 是 Google 用以帮助开发者在 iOS 和 Android 两个平 ...

  8. vue和哪个php框架搭配,vue配什么ui框架比较好

    Vue是一种用于构建用户界面的渐进式框架,它可以与各种框架或工具结合使用,如果是做PC端应用,选择ElementUI框架最好,做App移动端开发选择AUI或ionIc框架最好. Vue介绍: Vue是 ...

  9. dotnet Multi-platform App UI 多平台应用 UI 框架简介

    现在可以使用 .NET 构建一切应用.富有生产力的 .NET 是当前数百万的开发者选择这个平台的理由.在 .NET 5 微软统一了整个 .NET 平台,将 .NET Core 和 Mono 以及基于 ...

最新文章

  1. Python函数的非固定参数
  2. bagging and boosting
  3. python笔记之while和for循环练习
  4. KAFKA分布式消息系统
  5. 11-图像梯度-Sobel算子
  6. 计算机技术在工程施工中的应用,浅析计算机技术及网络在工程施工中的应用
  7. 【转】其实Unix很简单
  8. CentOS7通过定时脚本阻断异常IP连接SSH(实测)
  9. 数据库索引如何工作? [关闭]
  10. 《人月神话》读书笔记2--空间技能
  11. 如何在前端删除项目中的文件_如何在macOS上恢复已删除的文件
  12. 安卓4.2系统_五分钟了解 海贝(HiBy)R6PRO 安卓智能Hi-Fi播放器
  13. 车牌识别算法_向滥用远光灯说不,易泊车牌识别算法了解一下?
  14. 计算机基础雨课堂答案,基于“雨课堂”助推大学计算机基础课革新
  15. 使用python读写xlsx格式中的数据【xlrd、pywin32】
  16. m基于BP神经网络的障碍物避障和路线规划matlab仿真
  17. SequoiaDB 巨杉数据库-隔离级别
  18. 用python判断身份证号性别_验证身份证号的Python脚本
  19. 【Bluetooth蓝牙开发】九、BLE协议之GATT
  20. ubuntu不能检测到扩展副屏或双屏,不能使用键盘功能键,tweaks扩展动画消失的可能原因与可能的解决办法

热门文章

  1. oracle几种字符类型总结
  2. Project 2013 理论基础
  3. AI文案通过图灵测试!一秒生成2万条广告神器问世
  4. BIT琪露诺的完美算法教室 3.初上征途的za
  5. 【游戏开发创新】Unity 2D图片任意形状破碎碎裂效果,以此纪念我的牙光荣牺牲
  6. SAS——列联表(复习3)
  7. java基础学不会,转:《学不会的JAVA,消不了的忧愁》之四-JSP教程,Java基础
  8. 2018.12.10 第4题:定义两个类,描述如下: [必做题] 4.1定义一个人类Person: 4.1.1定义一个方法sayHello(),可以向对方发出问候语“hello,my name is
  9. 构造代码块、静态代码块、无参构造函数和有参构造函数的执行顺序
  10. 广告牌定时器怎么设置时间_定时开关怎么调整时间?