iOS Contacts 通訊錄 增刪改查 修改刪除的遇到的坑

1. 前情提要

在iOS9.0之后,系統(tǒng)的通訊錄改成了Contacts/Contacts.h,之前的AddressBook/AddressBook.h框架還可以用,而新的框架中采用的都是面向?qū)ο蟮乃枷耄奖恪?/p>

2. 首先導(dǎo)入頭文件

       #import <Contacts/Contacts.h>

3. 獲取授權(quán)信息

//    CNAuthorizationStatusNotDetermined = 0,
//    CNAuthorizationStatusRestricted,
//    CNAuthorizationStatusDenied,
//    CNAuthorizationStatusAuthorized

// 獲取授權(quán)狀態(tài)
//    [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];

// ios 9
CNContactStore *contactStore = [[CNContactStore alloc] init]; // 創(chuàng)建通訊錄
// 請求授權(quán)
[contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {

    if (granted) {
        NSLog(@"授權(quán)成功!");
// 添加聯(lián)系人
       // 獲取所有聯(lián)系人
    } else {
        NSLog(@"授權(quán)失敗!");
    }
}];

4. 獲取通訊錄

 // 1.獲取授權(quán)狀態(tài)
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
// 2.如果沒有授權(quán),先執(zhí)行授權(quán)失敗的block后return
if (status != CNAuthorizationStatusAuthorized)
{
    failure ? failure() : nil;
    return;
}
// 3.獲取聯(lián)系人
// 3.1.創(chuàng)建聯(lián)系人倉庫
CNContactStore *store = [[CNContactStore alloc] init];

// 3.2.創(chuàng)建聯(lián)系人的請求對象
// keys決定能獲取聯(lián)系人哪些信息,例:姓名,電話,頭像等
NSArray *fetchKeys = @[[CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName],CNContactPhoneNumbersKey,CNContactThumbnailImageDataKey];
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:fetchKeys];

// 3.3.請求聯(lián)系人
[self.contactStore enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact,BOOL * _Nonnull stop) {
    
    // 獲取聯(lián)系人全名
    NSString *name = [CNContactFormatter stringFromContact:contact style:CNContactFormatterStyleFullName];
    
    // 創(chuàng)建聯(lián)系人模型
    PPPersonModel *model = [PPPersonModel new];
    model.name = name.length > 0 ? name : @"無名氏" ;
    
    // 聯(lián)系人頭像
    model.headerImage = [UIImage imageWithData:contact.thumbnailImageData];
    
    // 獲取一個人的所有電話號碼
    NSArray *phones = contact.phoneNumbers;
    
    for (CNLabeledValue *labelValue in phones)
    {
        CNPhoneNumber *phoneNumber = labelValue.value;
        NSString *mobile = [self removeSpecialSubString:phoneNumber.stringValue];
        [model.mobileArray addObject: mobile ? mobile : @"空號"];
    }
    
  
}];

5. 添加聯(lián)系人

- (void)creatContact{

CNMutableContact *contact = [[CNMutableContact alloc] init]; // 第一次運行的時候,會獲取通訊錄的授權(quán)(對通訊錄進(jìn)行操作,有權(quán)限設(shè)置)

// 1、添加姓名(姓+名)
contact.givenName = @"san";
contact.familyName = @"wangg";

// 2、添加職位相關(guān)
contact.organizationName = @"公司名稱";
contact.departmentName = @"開發(fā)部門";
contact.jobTitle = @"工程師";

// 3、這一部分內(nèi)容會顯示在聯(lián)系人名字的下面,phoneticFamilyName屬性設(shè)置的話,會影響聯(lián)系人列表界面的排序
  //    contact.phoneticGivenName = @"GivenName";
  //    contact.phoneticFamilyName = @"FamilyName";
 //    contact.phoneticMiddleName = @"MiddleName";

// 4、備注
contact.note = @"同事";

// 5、頭像
contact.imageData = UIImagePNGRepresentation([UIImage imageNamed:@"1"]);

// 6、添加生日
NSDateComponents *birthday = [[NSDateComponents alloc] init];
birthday.year = 1990;
birthday.month = 6;
birthday.day = 6;
contact.birthday = birthday;

// 7、添加郵箱
CNLabeledValue *homeEmail = [CNLabeledValue labeledValueWithLabel:CNLabelEmailiCloud value:@"[bvbdsmv@icloud.com](mailto:bvbdsmv@icloud.com)"];
//    CNLabeledValue *workEmail = [CNLabeledValue labeledValueWithLabel:CNLabelWork value:@"11111888888"];
//    CNLabeledValue *iCloudEmail = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:@"34454554"];
//    CNLabeledValue *otherEmail = [CNLabeledValue labeledValueWithLabel:CNLabelOther value:@"6565448"];
contact.emailAddresses = @[homeEmail];

// 8、添加電話
CNLabeledValue *homePhone = [CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberiPhone value:[CNPhoneNumber phoneNumberWithStringValue:@"11122233344"]];
contact.phoneNumbers = @[homePhone];

// 9、添加urlAddresses,
CNLabeledValue *homeurl = [CNLabeledValue labeledValueWithLabel:CNLabelURLAddressHomePage value:@"[http://baidu.com](http://baidu.com)"];
contact.urlAddresses = @[homeurl];

// 10、添加郵政地址
CNMutablePostalAddress *postal = [[CNMutablePostalAddress alloc] init];
postal.city = @"北京";
postal.country =  @"中國";
CNLabeledValue *homePostal = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:postal];
contact.postalAddresses = @[homePostal];

// 獲取通訊錄操作請求對象
CNSaveRequest *request = [[CNSaveRequest alloc] init];
[request addContact:contact toContainerWithIdentifier:nil]; // 添加聯(lián)系人操作(同一個聯(lián)系人可以重復(fù)添加)
// 獲取通訊錄
CNContactStore *store = [[CNContactStore alloc] init];
// 保存聯(lián)系人
[store executeSaveRequest:request error:nil]; // 通訊錄有變化之后,還可以監(jiān)聽是否改變(CNContactStoreDidChangeNotification)

}

6. 刪除聯(lián)系人

- (void)deleteContact:(CNMutableContact *)contact{
// 創(chuàng)建聯(lián)系人請求
CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
[saveRequest deleteContact:contact];
// 寫入操作
CNContactStore *store = [[CNContactStore alloc] init];
[store executeSaveRequest:saveRequest error:nil];
}

7. 修改聯(lián)系人

- (void)updateContact:(CNMutableContact *)contact{
// 創(chuàng)建聯(lián)系人請求
CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
[saveRequest updateContact:contact];
// 重新寫入
CNContactStore *store = [[CNContactStore alloc] init];
[store executeSaveRequest:saveRequest error:nil];
}

8. 查找聯(lián)系人

- (NSArray *)queryContactWithName:(NSString *)name{

CNContactStore *store = [[CNContactStore alloc] init];
//檢索條件
NSPredicate *predicate = [CNContact predicateForContactsMatchingName:name];

//過濾的條件,也可以過濾時候格式化
NSArray *keysToFetch = @[CNContactEmailAddressesKey, [CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName]];

NSArray *contact = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keysToFetch error:nil];
return contact;
}

9. 修改刪除遇到的坑

通過查找聯(lián)系人,然后,進(jìn)行更新,刪除操作,
    NSArray *contact = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keysToFetch error:nil];

這一步獲得的是CNContact, 而 操作需要CNMutableContact,如直接修改會報錯

 NSPredicate *predicate = [CNContact predicateForContactsMatchingName:name];
NSArray *keysToFetch = @[CNContactPhoneNumbersKey,[CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName]];

NSArray *contacts = [self.contactStore unifiedContactsMatchingPredicate:predicate keysToFetch:keysToFetch error:nil];
if (contacts.count < 1) {
    [self addContactiOS9LaterName:name nums:nums];
    return;
}
CNContact *contact = contacts.firstObject;
CNMutableContact *contactM = (CNMutableContact *)[contact mutableCopy];

NSMutableArray *phoneNums = [NSMutableArray array];
for (NSString *num in nums) {
    CNPhoneNumber *number = [CNPhoneNumber phoneNumberWithStringValue:num];
    CNLabeledValue *phone = [[CNLabeledValue alloc]initWithLabel:CNLabelPhoneNumberiPhone value:number];
    [phoneNums addObject:phone];
}
contactM.phoneNumbers = [NSArray arrayWithArray:phoneNums];

CNSaveRequest *request = [[CNSaveRequest alloc]init];

[request updateContact:contactM];

NSError *error = nil;

[self.contactStore executeSaveRequest:request error:&error];

CNContact 要進(jìn)行一次 拷貝,并且, 在刪除或更新的項目, 查詢時候,一定要獲取到

  NSArray *keysToFetch = @[CNContactPhoneNumbersKey,
 [CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName]];

比如,我要修改聯(lián)系人名稱 跟 電話號碼, 就一定要寫查找的電話跟姓名的key. 否則會報錯

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,750評論 2 370

推薦閱讀更多精彩內(nèi)容