IOS开发中使用CNContact\CNMutableContact 对通讯录增删改查

首先当然是把CNcontact包含在工程中:

  1. @import Contacts;

1、下面是增加联系人的程序段:

  1. CNMutableContact * contact = [[CNMutableContact alloc]init];
  2. contact.imageData = UIImagePNGRepresentation([UIImage imageNamed:@""]);
  3. //设置名字
  4. contact.givenName = @"三强";
  5. //设置姓氏
  6. contact.familyName = @"钱";
  7. CNLabeledValue *homeEmail = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:@"316045346@qq.com"];
  8. CNLabeledValue *workEmail =[CNLabeledValue labeledValueWithLabel:CNLabelWork value:@"316045346@qq.com"];
  9. contact.emailAddresses = @[homeEmail,workEmail];
  10. //家庭
  11. CONTACTS_EXTERN NSString * const CNLabelHome NS_AVAILABLE(10_11, 9_0);
  12. //工作
  13. CONTACTS_EXTERN NSString * const CNLabelWork NS_AVAILABLE(10_11, 9_0);
  14. //其他
  15. CONTACTS_EXTERN NSString * const CNLabelOther NS_AVAILABLE(10_11, 9_0);
  16.  
  17. // 邮箱地址
  18. CONTACTS_EXTERN NSString * const CNLabelEmailiCloud NS_AVAILABLE(10_11, 9_0);
  19.  
  20. // url地址
  21. CONTACTS_EXTERN NSString * const CNLabelURLAddressHomePage NS_AVAILABLE(10_11, 9_0);
  22.  
  23. // 日期
  24. CONTACTS_EXTERN NSString * const CNLabelDateAnniversary NS_AVAILABLE(10_11, 9_0);
  25. contact.phoneNumbers = @[[CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberiPhone value:[CNPhoneNumber phoneNumberWithStringValue:@""]]];
  26. CNMutablePostalAddress * homeAdress = [[CNMutablePostalAddress alloc]init];
  27. homeAdress.street = @"贝克街";
  28. homeAdress.city = @"伦敦";
  29. homeAdress.state = @"英国";
  30. homeAdress.postalCode = @"221B";
  31. contact.postalAddresses = @[[CNLabeledValue labeledValueWithLabel:CNLabelHome value:homeAdress]];
  32. NSDateComponents * birthday = [[NSDateComponents alloc]init];
  33. birthday.day=;
  34. birthday.month=;
  35. birthday.year=;
  36. contact.birthday=birthday;
  37.  
  38. // //初始化方法
  39. CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];
  40. // 添加联系人(可以)
  41. [saveRequest addContact:contact toContainerWithIdentifier:nil];
  42. // 写入
  43. CNContactStore * store = [[CNContactStore alloc]init];
  44. [store executeSaveRequest:saveRequest error:nil];

2、下面是删除联系人的程序段,在苹果的开发文档中是这么描述的:

其中的contact参数是要被删除的联系人,也就以为这这个也就意味着这个联系人之前在通讯录存在,也就是说它不是我们新建的一个联系人对象,而是从通讯录中查出来的一个联系人对象,所以我们先要去查找联系人,这样的话先创建一个谓词,然后去查找,找到之后再执行删除,以下是程序段:

  1. // CNContactStore * store = [[CNContactStore alloc]init];
  2. // //检索条件,检索所有名字中GivenName是W的联系人
  3. // NSPredicate * predicate = [CNContact predicateForContactsMatchingName:@"W"];
  4. // //提取数据
  5. // NSArray * contacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:@[CNContactGivenNameKey] error:nil];
  6. // CNMutableContact *contact1 = [contacts objectAtIndex:0];
  7. //
  8. //
  9. //// //初始化方法
  10. // CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];
  11. //
  12. // //删除联系人(不行)
  13. // [saveRequest deleteContact:contact1];

3、关于更新联系人,在这里纠结了好久以下是整个过程,希望大家少走弯路:

1)、看到苹果的官方文档里,对这个updateContact方法轻描淡写,我也就没有注意,想想只要先把需要的联系人读出来,然后修改属性,并使用updateContact方法更新就行,然后我编写了以下程序(有问题的程序,灰色底色标注):

  1. CNContactStore * store = [[CNContactStore alloc]init];
  2. //检索条件,检索所有名字中有zhang的联系人
  3. NSPredicate * predicate = [CNContact predicateForContactsMatchingName:@"张"];
  4. //提取数据
  5. NSArray * contacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:@[CNContactGivenNameKey] error:nil];
  6. CNMutableContact *contact1 = [contacts objectAtIndex:];
  7. // 修改联系人的属性
  8. contact1.givenName = @"heh";
  9. // 实例化一个CNSaveRequest
  10. CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];
  11. [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类型的才能修改对象的属性并更新通讯录,而且要求要更新的联系人在通讯录中必须存在。于是我去苹果的官方手册里继续查找原因,然而并没找到如何读取一个联系人并读成可变类型的联系人的方法,我就继续翻翻,找各种可能性,后来被我看到一段代码:

  1. let mutableContact = contact.mutableCopy() as! CNMutableContact
  2. let newEmail = CNLabeledValue(label: CNLabelHome, value: "john@example.com")
  3. mutableContact.emailAddresses.append(newEmail)
  4.  
  5. let saveRequest = CNSaveRequest()
  6. saveRequest.updateContact(mutableContact)
  7. try! store.executeSaveRequest(saveRequest)

这段代码是swift语言写的,我先注意到第六行是saveRequest.updateContact,也就是说用了更新的语句,那么它更新的对象是什么类型呢?看看第一句就明白了,虽然我不懂swift,但看得出大概的意思是深拷贝(mutableCopy)了一个对象,那我也深拷贝一个呗,接下来我写了以下代码:

  1. CNContactStore * store = [[CNContactStore alloc]init];
  2. //检索条件,检索所有名字中有zhang的联系人
  3. NSPredicate * predicate = [CNContact predicateForContactsMatchingName:@"张"];
  4. //提取数据
  5. NSArray * contacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:@[CNContactGivenNameKey] error:nil];
  6. CNContact*contact1 = [contacts objectAtIndex:];
  7. CNMutableContact *contact2 = [contact1 mutableCopy];
  8. // 修改联系人的属性
  9. contact2.givenName = @"asdfasdfas";
  10. // 实例化一个CNSaveRequest
  11. CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];
  12. [saveRequest updateContact:contact2];

满怀希望的运行,发现并没有修改我的联系人,接下来继续找问题,修改成以下代码:

  1. CNContactStore * store = [[CNContactStore alloc]init];
  2. //检索条件,检索所有名字中有zhang的联系人
  3. NSPredicate * predicate = [CNContact predicateForContactsMatchingName:@"张"];
  4. //提取数据
  5. NSArray * contacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:@[CNContactGivenNameKey] error:nil];
  6. CNMutableContact *contact2 = [[contacts objectAtIndex:] mutableCopy];
  7. // 修改联系人的属性
  8. contact2.givenName = @"asdfasdfas";
  9. // 实例化一个CNSaveRequest
  10. CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];
  11. [saveRequest updateContact:contact2];

还是不行,继续去找苹果的茬,再读读上面发现的那段代码:

  1. let mutableContact = contact.mutableCopy() as! CNMutableContact
  2. let newEmail = CNLabeledValue(label: CNLabelHome, value: "john@example.com")
  3. mutableContact.emailAddresses.append(newEmail)
  4.  
  5. let saveRequest = CNSaveRequest()
  6. saveRequest.updateContact(mutableContact)
  7. try! store.executeSaveRequest(saveRequest)

发现第七句,我这儿没有用,想起使用addContact方法新增联系人到通讯录的时候最后要用这句,那就加上这句吧:

  1. CNContactStore * store = [[CNContactStore alloc]init];
  2. //检索条件,检索所有名字中有zhang的联系人
  3. NSPredicate * predicate = [CNContact predicateForContactsMatchingName:@"张"];
  4. //提取数据
  5. NSArray * contacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:@[CNContactGivenNameKey] error:nil];
  6. CNMutableContact *contact2 = [[contacts objectAtIndex:] mutableCopy];
  7. // 修改联系人的属性
  8. contact2.givenName = @"asdfasdfas";
  9. // 实例化一个CNSaveRequest
  10. CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];
  11. [saveRequest updateContact:contact2];
  12. [store executeSaveRequest:saveRequest error:nil];

再次运行,并打到模拟器的通讯录,惊喜的发现姓张的联系人变成名字变成了asdfasdfas,见下图:

这就是结果,在看看我是在哪儿找到苹果的官方文档里面的那段代码的出处:

IOS开发中使用CNContact\CNMutableContact 对通讯录增删改查的更多相关文章

  1. iOS开发——数据持久化OC篇&plist文件增删改查操作

    Plist文件增删查改   主要操作: 1.//获得plist路径    -(NSString*)getPlistPath: 2.//判断沙盒中名为plistname的文件是否存在    -(BOOL ...

  2. IOS9中联系人对象的使用及增删改查操作的函数封装

    之前克服重重困难把IOS9中新的类联系人搞明白了,现在把增删改查封装成了函数,如下: // // ViewController.m // IOS9中联系人CNContact的使用 // // Crea ...

  3. iOS云存储:CloudKit 基本使用教程 增删改查(Swift)

    一.从iOS8开始,苹果为开发者提供了ClouKit,可以把我们的应用程序和用户数据存储在iCloud上,用于代替后台服务器,开发移动代码即可. 二.设置 (1)需要一个开发者账号,并且设置一个bun ...

  4. 一个在ASP.NET中利用服务器控件GridView实现数据增删改查的例子

    备注:这是我辅导的一个项目开发组的一个例子,用文章的方式分享出来,给更多的朋友参考.其实我们这几年的项目中,都不怎么使用服务器控件的形式了,而是更多的采用MVC这种开发模式.但是,如果项目的历史背景是 ...

  5. 基于 abp vNext 和 .NET Core 开发博客项目 - 自定义仓储之增删改查

    上一篇文章(https://www.cnblogs.com/meowv/p/12913676.html)我们用Code-First的方式创建了博客所需的实体类,生成了数据库表,完成了对EF Core的 ...

  6. mongodb windows的安装方法和添加到任务管理器中、检测是否成功、增删改查命令

    转: mongodb安装方法: https://blog.csdn.net/heshushun/article/details/77776706        mongodb检测安装成功 .以及增删改 ...

  7. Ado.net中简单的DBHelper类(增删改查)

    private static string connString = "server=.;database=hotel;uid=aa;pwd=123";//最好从配置文件中取出 p ...

  8. Python中列表、元组、字典增删改查基本区别

    1.定义: 列表:num = ["a","b"."c"] ##定义后可增删改查 元组:num = ("a"," ...

  9. django中数据库的配置及相关增删改查

    ORM ORM是什么?:(在django中,根据代码中的类自动生成数据库的表也叫--code first) ORM:Object Relational Mapping(关系对象映射) 类名对应---- ...

随机推荐

  1. UVALive 4992 Jungle Outpost(半平面交)

    题意:给你n个塔(点)形成一个顺时针的凸包,敌人可以摧毁任何塔,摧毁后剩下的塔再组成凸包 在开始的凸包内选一点为主塔,保证敌人摧毁尽量多塔时主塔都还在现在的凸包内,求出最多摧毁的塔 题解:这题关键就是 ...

  2. 利用工具MailUtils实现邮件的发送,遇到的大坑,高能预警!!

    java实现邮件的发送依赖的jar包有两个:mail.jar和activation.jar,我也找到了一个工具包:itcast-tools-1.4.jar,实现原理大家可以查看源码,先放出资源链接 h ...

  3. Oracle数据库设计小细节

    1. 如果使用PowerDesigner此类工具,注意将工具的导出的SQL语句中对于表的双引号去掉. 2. 建表和建字段的时候,不同单词之间使用下划线分隔,比如 REC_ID 3. Oracle中数值 ...

  4. 认识和选用常用的几种 GPRS 模块(转)

    源:http://blog.sina.com.cn/s/blog_4d80055a0100e8kr.html 我在这里把常见的GPRS模块分成3种: (1)GPRS DTU(GPRS数传单元,常称GP ...

  5. 2016大连网络赛 Weak Pair

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Prob ...

  6. hihoCoder 1257 Snake Carpet(很简单的构造方法)

    2015 ACM / ICPC 北京现场赛 I 题 构造 注意一个小坑,每条蛇的输出是要从头到尾输出的. 还要注意的是,不能开数组去模拟构造过程,然后输出,那样会TLE的. #include < ...

  7. Qt5:随窗口大小变化背景图片自动缩放的实现

    在窗口程序中,当我们改变窗口大小的时候,背景图片通常会岁窗口大小变化而缩放 然而,在我们写的窗口程序中,设置背景图片后,如果缩放大小,会看到背景图片并不会随之缩放, 应为这需要特殊处理,一般常用的方法 ...

  8. Qt5:不规则按钮的实现---通过贴图实现

    在应用开发中,有时候为了美观会在UI界面中增加不规则的按钮 现在我们就来看看Qt中是怎么实现不规则按钮的 /////////////////////////////////////////////// ...

  9. win8 explorer 进程频繁奔溃的原因及处理

    最近  ,  win8 系统中的 explorer 进程总是频繁奔溃    ,    想想可能是最近新装或更新了什么软件引起的 . 查看了记录奔溃的详细信息 ,  果不其然 , 是最近更新的快播新版本 ...

  10. cmd 3389

    1.2000系统 简要说一下如何进行DNS溢出攻击.我用的溢出利用程序是dns.exe,在CMD下运行它可以看到它的使用参数等信息.执行"dns -s IP"命令检测目标IP是否存 ...