IOS开发中使用CNContact\CNMutableContact 对通讯录增删改查
IOS开发中使用CNContact\CNMutableContact 对通讯录增删改查
首先当然是把CNcontact包含在工程中:
- @import Contacts;
1、下面是增加联系人的程序段:
- CNMutableContact * contact = [[CNMutableContact alloc]init];
- contact.imageData = UIImagePNGRepresentation([UIImage imageNamed:@""]);
- //设置名字
- contact.givenName = @"三强";
- //设置姓氏
- contact.familyName = @"钱";
- CNLabeledValue *homeEmail = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:@"316045346@qq.com"];
- CNLabeledValue *workEmail =[CNLabeledValue labeledValueWithLabel:CNLabelWork value:@"316045346@qq.com"];
- contact.emailAddresses = @[homeEmail,workEmail];
- //家庭
- 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:@""]]];
- CNMutablePostalAddress * homeAdress = [[CNMutablePostalAddress alloc]init];
- homeAdress.street = @"贝克街";
- homeAdress.city = @"伦敦";
- homeAdress.state = @"英国";
- homeAdress.postalCode = @"221B";
- contact.postalAddresses = @[[CNLabeledValue labeledValueWithLabel:CNLabelHome value:homeAdress]];
- NSDateComponents * birthday = [[NSDateComponents alloc]init];
- birthday.day=;
- birthday.month=;
- birthday.year=;
- contact.birthday=birthday;
- // //初始化方法
- CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];
- // 添加联系人(可以)
- [saveRequest addContact:contact toContainerWithIdentifier:nil];
- // 写入
- CNContactStore * store = [[CNContactStore alloc]init];
- [store executeSaveRequest:saveRequest error:nil];
2、下面是删除联系人的程序段,在苹果的开发文档中是这么描述的:
其中的contact参数是要被删除的联系人,也就以为这这个也就意味着这个联系人之前在通讯录存在,也就是说它不是我们新建的一个联系人对象,而是从通讯录中查出来的一个联系人对象,所以我们先要去查找联系人,这样的话先创建一个谓词,然后去查找,找到之后再执行删除,以下是程序段:
- // CNContactStore * store = [[CNContactStore alloc]init];
- // //检索条件,检索所有名字中GivenName是W的联系人
- // NSPredicate * predicate = [CNContact predicateForContactsMatchingName:@"W"];
- // //提取数据
- // NSArray * contacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:@[CNContactGivenNameKey] error:nil];
- // CNMutableContact *contact1 = [contacts objectAtIndex:0];
- //
- //
- //// //初始化方法
- // CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];
- //
- // //删除联系人(不行)
- // [saveRequest deleteContact:contact1];
3、关于更新联系人,在这里纠结了好久以下是整个过程,希望大家少走弯路:
1)、看到苹果的官方文档里,对这个updateContact方法轻描淡写,我也就没有注意,想想只要先把需要的联系人读出来,然后修改属性,并使用updateContact方法更新就行,然后我编写了以下程序(有问题的程序,灰色底色标注):
- CNContactStore * store = [[CNContactStore alloc]init];
- //检索条件,检索所有名字中有zhang的联系人
- NSPredicate * predicate = [CNContact predicateForContactsMatchingName:@"张"];
- //提取数据
- NSArray * contacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:@[CNContactGivenNameKey] error:nil];
- CNMutableContact *contact1 = [contacts objectAtIndex:];
- // 修改联系人的属性
- contact1.givenName = @"heh";
- // 实例化一个CNSaveRequest
- CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];
- [saveRequest updateContact:contact1];
但是以上程序段运行的时候总会提示错误,并且crash掉,错误提示是:
-[CNContact setGivenName:]: unrecognized selector sent to instance 0x7fd5ba755660
然后Add一个Expection Breakpoint,程序总是运行到修改联系人属性这句卡住,见下图:
然后就很纠结啊,上网查找原因,在QQ群里问大神,得到的答案是对象被提前释放了,然后我也有这个感觉,我打断点调试,发现当运行CNMutableContact *contact1 = [contacts objectAtIndex:0];这句之后,contact1就变成了CNContact类型的对象,不再是CNMutableContact。而苹果官方文档要求要更新或者添加一个联系人到通讯录,首先要求这个对象是可变的,也就是只有CNMutableContact类型的才能修改对象的属性并更新通讯录,而且要求要更新的联系人在通讯录中必须存在。于是我去苹果的官方手册里继续查找原因,然而并没找到如何读取一个联系人并读成可变类型的联系人的方法,我就继续翻翻,找各种可能性,后来被我看到一段代码:
- let mutableContact = contact.mutableCopy() as! CNMutableContact
- let newEmail = CNLabeledValue(label: CNLabelHome, value: "john@example.com")
- mutableContact.emailAddresses.append(newEmail)
- let saveRequest = CNSaveRequest()
- saveRequest.updateContact(mutableContact)
- try! store.executeSaveRequest(saveRequest)
这段代码是swift语言写的,我先注意到第六行是saveRequest.updateContact,也就是说用了更新的语句,那么它更新的对象是什么类型呢?看看第一句就明白了,虽然我不懂swift,但看得出大概的意思是深拷贝(mutableCopy)了一个对象,那我也深拷贝一个呗,接下来我写了以下代码:
- CNContactStore * store = [[CNContactStore alloc]init];
- //检索条件,检索所有名字中有zhang的联系人
- NSPredicate * predicate = [CNContact predicateForContactsMatchingName:@"张"];
- //提取数据
- NSArray * contacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:@[CNContactGivenNameKey] error:nil];
- CNContact*contact1 = [contacts objectAtIndex:];
- CNMutableContact *contact2 = [contact1 mutableCopy];
- // 修改联系人的属性
- contact2.givenName = @"asdfasdfas";
- // 实例化一个CNSaveRequest
- CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];
- [saveRequest updateContact:contact2];
满怀希望的运行,发现并没有修改我的联系人,接下来继续找问题,修改成以下代码:
- CNContactStore * store = [[CNContactStore alloc]init];
- //检索条件,检索所有名字中有zhang的联系人
- NSPredicate * predicate = [CNContact predicateForContactsMatchingName:@"张"];
- //提取数据
- NSArray * contacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:@[CNContactGivenNameKey] error:nil];
- CNMutableContact *contact2 = [[contacts objectAtIndex:] mutableCopy];
- // 修改联系人的属性
- contact2.givenName = @"asdfasdfas";
- // 实例化一个CNSaveRequest
- CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];
- [saveRequest updateContact:contact2];
还是不行,继续去找苹果的茬,再读读上面发现的那段代码:
- let mutableContact = contact.mutableCopy() as! CNMutableContact
- let newEmail = CNLabeledValue(label: CNLabelHome, value: "john@example.com")
- mutableContact.emailAddresses.append(newEmail)
- let saveRequest = CNSaveRequest()
- saveRequest.updateContact(mutableContact)
- try! store.executeSaveRequest(saveRequest)
发现第七句,我这儿没有用,想起使用addContact方法新增联系人到通讯录的时候最后要用这句,那就加上这句吧:
- CNContactStore * store = [[CNContactStore alloc]init];
- //检索条件,检索所有名字中有zhang的联系人
- NSPredicate * predicate = [CNContact predicateForContactsMatchingName:@"张"];
- //提取数据
- NSArray * contacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:@[CNContactGivenNameKey] error:nil];
- CNMutableContact *contact2 = [[contacts objectAtIndex:] mutableCopy];
- // 修改联系人的属性
- contact2.givenName = @"asdfasdfas";
- // 实例化一个CNSaveRequest
- CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];
- [saveRequest updateContact:contact2];
- [store executeSaveRequest:saveRequest error:nil];
再次运行,并打到模拟器的通讯录,惊喜的发现姓张的联系人变成名字变成了asdfasdfas,见下图:
这就是结果,在看看我是在哪儿找到苹果的官方文档里面的那段代码的出处:
IOS开发中使用CNContact\CNMutableContact 对通讯录增删改查的更多相关文章
- iOS开发——数据持久化OC篇&plist文件增删改查操作
Plist文件增删查改 主要操作: 1.//获得plist路径 -(NSString*)getPlistPath: 2.//判断沙盒中名为plistname的文件是否存在 -(BOOL ...
- IOS9中联系人对象的使用及增删改查操作的函数封装
之前克服重重困难把IOS9中新的类联系人搞明白了,现在把增删改查封装成了函数,如下: // // ViewController.m // IOS9中联系人CNContact的使用 // // Crea ...
- iOS云存储:CloudKit 基本使用教程 增删改查(Swift)
一.从iOS8开始,苹果为开发者提供了ClouKit,可以把我们的应用程序和用户数据存储在iCloud上,用于代替后台服务器,开发移动代码即可. 二.设置 (1)需要一个开发者账号,并且设置一个bun ...
- 一个在ASP.NET中利用服务器控件GridView实现数据增删改查的例子
备注:这是我辅导的一个项目开发组的一个例子,用文章的方式分享出来,给更多的朋友参考.其实我们这几年的项目中,都不怎么使用服务器控件的形式了,而是更多的采用MVC这种开发模式.但是,如果项目的历史背景是 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - 自定义仓储之增删改查
上一篇文章(https://www.cnblogs.com/meowv/p/12913676.html)我们用Code-First的方式创建了博客所需的实体类,生成了数据库表,完成了对EF Core的 ...
- mongodb windows的安装方法和添加到任务管理器中、检测是否成功、增删改查命令
转: mongodb安装方法: https://blog.csdn.net/heshushun/article/details/77776706 mongodb检测安装成功 .以及增删改 ...
- Ado.net中简单的DBHelper类(增删改查)
private static string connString = "server=.;database=hotel;uid=aa;pwd=123";//最好从配置文件中取出 p ...
- Python中列表、元组、字典增删改查基本区别
1.定义: 列表:num = ["a","b"."c"] ##定义后可增删改查 元组:num = ("a"," ...
- django中数据库的配置及相关增删改查
ORM ORM是什么?:(在django中,根据代码中的类自动生成数据库的表也叫--code first) ORM:Object Relational Mapping(关系对象映射) 类名对应---- ...
随机推荐
- UVALive 4992 Jungle Outpost(半平面交)
题意:给你n个塔(点)形成一个顺时针的凸包,敌人可以摧毁任何塔,摧毁后剩下的塔再组成凸包 在开始的凸包内选一点为主塔,保证敌人摧毁尽量多塔时主塔都还在现在的凸包内,求出最多摧毁的塔 题解:这题关键就是 ...
- 利用工具MailUtils实现邮件的发送,遇到的大坑,高能预警!!
java实现邮件的发送依赖的jar包有两个:mail.jar和activation.jar,我也找到了一个工具包:itcast-tools-1.4.jar,实现原理大家可以查看源码,先放出资源链接 h ...
- Oracle数据库设计小细节
1. 如果使用PowerDesigner此类工具,注意将工具的导出的SQL语句中对于表的双引号去掉. 2. 建表和建字段的时候,不同单词之间使用下划线分隔,比如 REC_ID 3. Oracle中数值 ...
- 认识和选用常用的几种 GPRS 模块(转)
源:http://blog.sina.com.cn/s/blog_4d80055a0100e8kr.html 我在这里把常见的GPRS模块分成3种: (1)GPRS DTU(GPRS数传单元,常称GP ...
- 2016大连网络赛 Weak Pair
Weak Pair Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) Prob ...
- hihoCoder 1257 Snake Carpet(很简单的构造方法)
2015 ACM / ICPC 北京现场赛 I 题 构造 注意一个小坑,每条蛇的输出是要从头到尾输出的. 还要注意的是,不能开数组去模拟构造过程,然后输出,那样会TLE的. #include < ...
- Qt5:随窗口大小变化背景图片自动缩放的实现
在窗口程序中,当我们改变窗口大小的时候,背景图片通常会岁窗口大小变化而缩放 然而,在我们写的窗口程序中,设置背景图片后,如果缩放大小,会看到背景图片并不会随之缩放, 应为这需要特殊处理,一般常用的方法 ...
- Qt5:不规则按钮的实现---通过贴图实现
在应用开发中,有时候为了美观会在UI界面中增加不规则的按钮 现在我们就来看看Qt中是怎么实现不规则按钮的 /////////////////////////////////////////////// ...
- win8 explorer 进程频繁奔溃的原因及处理
最近 , win8 系统中的 explorer 进程总是频繁奔溃 , 想想可能是最近新装或更新了什么软件引起的 . 查看了记录奔溃的详细信息 , 果不其然 , 是最近更新的快播新版本 ...
- cmd 3389
1.2000系统 简要说一下如何进行DNS溢出攻击.我用的溢出利用程序是dns.exe,在CMD下运行它可以看到它的使用参数等信息.执行"dns -s IP"命令检测目标IP是否存 ...