zoukankan      html  css  js  c++  java
  • IOS开发中使用CNContactCNMutableContact 对通讯录增删改查

    IOS开发中使用CNContactCNMutableContact 对通讯录增删改查

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

    1 @import Contacts;

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

     1 CNMutableContact * contact = [[CNMutableContact alloc]init];
     2     contact.imageData = UIImagePNGRepresentation([UIImage imageNamed:@"22"]);
     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:@"12344312321"]]];
    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=7;
    34     birthday.month=5;
    35     birthday.year=1992;
    36     contact.birthday=birthday;
    37     
    38     
    39     
    40     
    41     //    //初始化方法
    42     CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];
    43     //    添加联系人(可以)
    44     [saveRequest addContact:contact toContainerWithIdentifier:nil];
    45     //    写入
    46     CNContactStore * store = [[CNContactStore alloc]init];
    47     [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:0];
     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:0];
     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:0] 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:0] 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,见下图:

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

  • 相关阅读:
    用价值链分析软件开发及杂感
    《恰如其分的软件架构》笔记摘要
    观察者模式
    Js中Date对象
    Js中Currying的应用
    read命令
    模板方法模式
    两两交换链表中的节点
    享元模式
    Js中Array对象
  • 原文地址:https://www.cnblogs.com/jiwangbujiu/p/5467302.html
Copyright © 2011-2022 走看看