公司項目有訪問通訊錄的需求,所以開始了探索之路。從開始的一無所知,到知識的漸漸清晰。這一切要感謝廣大無私分享的 “coder”,註:我是尊稱的語氣! 蘋果提供了訪問系統通訊錄的框架,以便開發者對系統通訊錄進行操作。(此demo為純代碼),想要訪問通訊錄,需要添加AddressBookUI.frame
公司項目有訪問通訊錄的需求,所以開始了探索之路。從開始的一無所知,到知識的漸漸清晰。這一切要感謝廣大無私分享的 “coder”,註:我是尊稱的語氣!
蘋果提供了訪問系統通訊錄的框架,以便開發者對系統通訊錄進行操作。(此demo為純代碼),想要訪問通訊錄,需要添加AddressBookUI.framework和AddressBook.framework兩個框架,添加的地點這裡就不在贅述了。在控制器內部首先import兩個頭文件,<AddressBook/AddressBook.h> 和 <AddressBookUI/AddressBookUI.h>,如下圖所示:
1 // 2 // ZBSampleViewController.m 3 // ZBAddressBookDemo 4 // 5 // Created by zhangb on 16/02/04. 6 // Copyright (c) 2016年 mbp. All rights reserved. 7 // 8 9 #import "ZBSampleViewController.h" 10 #import <AddressBook/AddressBook.h> 11 #import <AddressBookUI/AddressBookUI.h>
首先為了方便演示與操作,這裡就以兩個按鈕的操作代替具體的訪問過程,當然具體操作要具體分析,這裡只是記錄訪問通訊錄,包括:1)查看聯繫人 2)向通訊錄內添加聯繫人。下麵是代碼示例:
ABPeoplePickerNavigationController為展示系統通訊錄的控制器,並且需要遵循其代理方法。
1 #define IS_iOS8 [[UIDevice currentDevice].systemVersion floatValue] >= 8.0f 2 #define IS_iOS6 [[UIDevice currentDevice].systemVersion floatValue] >= 6.0f 3 4 @interface ZBSampleViewController ()<ABPeoplePickerNavigationControllerDelegate>{ 5 6 ABPeoplePickerNavigationController *_abPeoplePickerVc; 7 8 }
1 - (void)viewDidLoad { 2 [super viewDidLoad]; 3 4 //1.打開通訊錄 5 UIButton *openAddressBook = [UIButton buttonWithType:UIButtonTypeCustom]; 6 openAddressBook.frame = CGRectMake(100, 50, 100, 50); 7 [openAddressBook setTitle:@"打開通訊錄" forState:UIControlStateNormal]; 8 openAddressBook.backgroundColor = [UIColor greenColor]; 9 [openAddressBook setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 10 [openAddressBook addTarget:self action:@selector(gotoAddressBook) forControlEvents:UIControlEventTouchUpInside]; 11 [self.view addSubview:openAddressBook]; 12 13 //2.添加聯繫人 14 UIButton *addContacts = [UIButton buttonWithType:UIButtonTypeCustom]; 15 addContacts.frame = CGRectMake(100, 150, 100, 50); 16 [addContacts setTitle:@"添加聯繫人" forState:UIControlStateNormal]; 17 addContacts.backgroundColor = [UIColor greenColor]; 18 [addContacts setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 19 [addContacts addTarget:self action:@selector(gotoAddContacts) forControlEvents:UIControlEventTouchUpInside]; 20 [self.view addSubview:addContacts]; 21 22 }
打開系統通訊錄方法為openAddressBook按鈕的點擊事件,請忽略按鈕的樣式O(∩_∩)O~;
下麵的IS_iOS8為我定義的巨集,判斷系統的版本(上面有代碼示例)。
1 /** 2 打開通訊錄 3 */ 4 - (void)gotoAddressBook{ 5 6 _abPeoplePickerVc = [[ABPeoplePickerNavigationController alloc] init]; 7 _abPeoplePickerVc.peoplePickerDelegate = self; 8 9 //下麵的判斷是ios8之後才需要加的,不然會自動返回app內部 10 if(IS_iOS8){ 11 12 //predicateForSelectionOfPerson預設是true (當你點擊某個聯繫人查看詳情的時候會返回app),如果你預設為true 但是實現-peoplePickerNavigationController:didSelectPerson:property:identifier:
代理方法也是可以的,與此同時不能實現peoplePickerNavigationController: didSelectPerson:不然還是會返回app。 13 //總之在ios8之後加上此句比較穩妥 14 _abPeoplePickerVc.predicateForSelectionOfPerson = [NSPredicate predicateWithValue:false]; 15 16 //predicateForSelectionOfProperty預設是true (當你點擊某個聯繫人的某個屬性的時候會返回app),此方法只要是預設值,無論你代理方法實現與否都會返回app。 17 // _abPeoplePickerVc.predicateForSelectionOfProperty = [NSPredicate predicateWithValue:false]; 18 19 //predicateForEnablingPerson預設是true,當設置為false時,所有的聯繫人都不能被點擊。 20 // _abPeoplePickerVc.predicateForEnablingPerson = [NSPredicate predicateWithValue:true]; 21 } 22 [self presentViewController:_abPeoplePickerVc animated:YES completion:nil]; 23 24 }
這裡需要註意的是:
在iOS8之後需要加_abPeoplePickerVc.predicateForSelectionOfPerson = [NSPredicate predicateWithValue:false];這句代碼,不然當你選擇通訊錄中的某個聯繫人的時候會直接返回app內部(類似crash)。predicateForSelectionOfPerson預設是true (當你點擊某個聯繫人查看詳情的時候會返回app),如果你預設為true 但是實現-peoplePickerNavigationController:didSelectPerson:property:identifier: 代理方法也是可以的,與此同時不能實現peoplePickerNavigationController: didSelectPerson:不然還是會返回app。
_abPeoplePickerVc.predicateForSelectionOfProperty = [NSPredicate predicateWithValue:false];作用同上。但是_abPeoplePickerVc.predicateForEnablingPerson 的斷言語句必須為true,否則任何聯繫人你都不能選擇。上面的代碼中也有詳細描述。
1 #pragma mark - ABPeoplePickerNavigationController的代理方法 2 3 - (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier { 4 5 ABMultiValueRef phone = ABRecordCopyValue(person, kABPersonPhoneProperty); 6 7 long index = ABMultiValueGetIndexForIdentifier(phone,identifier); 8 9 NSString *phoneNO = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phone, index); 10 [phoneNO stringByReplacingOccurrencesOfString:@"-" withString:@""]; 11 if (phone && phoneNO.length == 11) { 12 //TODO:獲取電話號碼要做的事情 13 14 [peoplePicker dismissViewControllerAnimated:YES completion:nil]; 15 return; 16 }else{ 17 if (IS_iOS8){ 18 UIAlertController *tipVc = [UIAlertController alertControllerWithTitle:nil message:@"請選擇正確手機號" preferredStyle:UIAlertControllerStyleAlert]; 19 UIAlertAction *cancleAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { 20 [self dismissViewControllerAnimated:YES completion:nil]; 21 }]; 22 [tipVc addAction:cancleAction]; 23 [self presentViewController:tipVc animated:YES completion:nil]; 24 25 }else{ 26 UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:@"請選擇正確手機號" delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil]; 27 [alertView show]; 28 } 29 //非ARC模式需要釋放對象 30 // [alertView release]; 31 } 32 } 33 34 35 - (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person NS_AVAILABLE_IOS(8_0) 36 { 37 ABPersonViewController *personViewController = [[ABPersonViewController alloc] init]; 38 personViewController.displayedPerson = person; 39 40 [peoplePicker pushViewController:personViewController animated:YES]; 41 //非ARC模式需要釋放對象 42 // [personViewController release]; 43 } 44 45 /** 46 peoplePickerNavigationController點擊取消按鈕時調用 47 */ 48 - (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker 49 { 50 [peoplePicker dismissViewControllerAnimated:YES completion:nil]; 51 } 52 53 /** 54 iOS8被廢棄了,iOS8前查看聯繫人必須實現(點擊聯繫人可以繼續操作) 55 */ 56 - (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person NS_DEPRECATED_IOS(2_0, 8_0) 57 { 58 return YES; 59 } 60 61 /** 62 iOS8被廢棄了,iOS8前查看聯繫人屬性必須實現(點擊聯繫人屬性可以繼續操作) 63 */ 64 - (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier NS_DEPRECATED_IOS(2_0, 8_0) 65 { 66 ABMultiValueRef phone = ABRecordCopyValue(person, kABPersonPhoneProperty); 67 68 long index = ABMultiValueGetIndexForIdentifier(phone,identifier); 69 70 NSString *phoneNO = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phone, index); 71 phoneNO = [phoneNO stringByReplacingOccurrencesOfString:@"-" withString:@""]; 72 NSLog(@"%@", phoneNO); 73 if (phone && phoneNO.length == 11) { 74 //TODO:獲取電話號碼要做的事情 75 76 [peoplePicker dismissViewControllerAnimated:YES completion:nil]; 77 return NO; 78 }else{ 79 if (IS_iOS8){ 80 UIAlertController *tipVc = [UIAlertController alertControllerWithTitle:nil message:@"請選擇正確手機號" preferredStyle:UIAlertControllerStyleAlert]; 81 UIAlertAction *cancleAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { 82 [self dismissViewControllerAnimated:YES completion:nil]; 83 }]; 84 [tipVc addAction:cancleAction]; 85 [self presentViewController:tipVc animated:YES completion:nil]; 86 87 }else{ 88 UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:@"請選擇正確手機號" delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil]; 89 [alertView show]; 90 } 91 } 92 return YES; 93 }
ABPeoplePickerNavigationController的代理方法也很好理解,看字面意思就能夠猜出代理方法的執行時間與能夠做什麼。拿第一個代理方法說明一下,也就是- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier;第一個參數就不用說了,第二個參數 ABRecordRef 這是一個聯繫人的引用也可以說是一個記錄,你可以理解為一個聯繫人。第三個參數是聯繫人附帶屬性的ID,其實ABPropertyID是個int類型值。第四個參數是多值屬性的標簽。
ABRecordCopyValue(ABRecordRef record, ABPropertyID property)返回一個CFTypeRef類型。此方法是從系統的通訊錄內,copy出用戶所選擇的某個聯繫人數據。返回類型要看參數傳遞的是什麼,第一個參數是聯繫人記錄,第二個參數是參數ID,也就是用戶選擇的聯繫人的某個屬性的ID。kABPersonPhoneProperty代表的是手機號碼屬性的ID,假如上面的ABRecordCopyValue的第二個參數傳遞kABPersonAddressProperty,則返回的是聯繫人的地址屬性。下麵是效果圖(因為是模擬器和真機有些差異)。
下麵介紹下,向系統通訊錄內添加聯繫人。這裡我只設置了聯繫人的三個屬性:名字,電話,郵件,並將屬性存在了字典里。
1 -(instancetype)init{ 2 if (self = [super init]) { 3 _infoDictionary = [NSMutableDictionary dictionaryWithCapacity:0]; 4 [_infoDictionary setObject:@"張三" forKey:@"name"]; 5 [_infoDictionary setObject:@"13000000000" forKey:@"phone"]; 6 [_infoDictionary setObject:@"[email protected]" forKey:@"email"]; 7 } 8 return self; 9 }
因為蘋果越來越註重保護用戶的隱私,現在需要修改系統通訊錄內的聯繫人信息時,必須要用戶授權才可以進行。授權鑒定代碼為ABAddressBookRequestAccessWithCompletion(ABAddressBookRef addressBook, ABAddressBookRequestAccessCompletionHandler completion) __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0);下麵的代碼中都有詳細描述。
1 /** 2 添加聯繫人 3 */ 4 - (void)gotoAddContacts{ 5 6 //添加到通訊錄,判斷通訊錄是否存在 7 if ([self isExistContactPerson]) {//存在,返回 8 //提示 9 if (IS_iOS8) { 10 UIAlertController *tipVc = [UIAlertController alertControllerWithTitle:@"提示" message:@"聯繫人已存在..." preferredStyle:UIAlertControllerStyleAlert]; 11 UIAlertAction *cancleAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { 12 [self dismissViewControllerAnimated:YES completion:nil]; 13 }]; 14 [tipVc addAction:cancleAction]; 15 [self presentViewController:tipVc animated:YES completion:nil]; 16 }else{ 17 UIAlertView *tip = [[UIAlertView alloc] initWithTitle:@"提示" message:@"聯繫人已存在..." delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil, nil]; 18 [tip show]; 19 // [tip release]; 20 } 21 return; 22 }else{//不存在 添加 23 [self creatNewRecord]; 24 } 25 } 26 27 - (BOOL)isExistContactPerson{ 28 //這個變數用於記錄授權是否成功,即用戶是否允許我們訪問通訊錄 29 int __block tip=0; 30 31 BOOL __block isExist = NO; 32 //聲明一個通訊簿的引用 33 ABAddressBookRef addBook =nil; 34 //因為在IOS6.0之後和之前的許可權申請方式有所差別,這裡做個判斷 35 if (IS_iOS6) { 36 //創建通訊簿的引用,第一個參數暫時寫NULL,官方文檔就是這麼說的,後續會有用,第二個參數是error參數 37 CFErrorRef error = NULL; 38 addBook=ABAddressBookCreateWithOptions(NULL, &error); 39 //創建一個初始信號量為0的信號 40 dispatch_semaphore_t sema=dispatch_semaphore_create(0); 41 //申請訪問許可權 42 ABAddressBookRequestAccessWithCompletion(addBook, ^(bool greanted, CFErrorRef error) { 43 //greanted為YES是表示用戶允許,否則為不允許 44 if (!greanted) { 45 tip=1; 46 47 }else{ 48 //獲取所有聯繫人的數組 49 CFArrayRef allLinkPeople = ABAddressBookCopyArrayOfAllPeople(addBook); 50 //獲取聯繫人總數 51 CFIndex number = ABAddressBookGetPersonCount(addBook); 52 //進行遍歷 53 for (NSInteger i=0; i<number; i++) { 54 //獲取聯繫人對象的引用 55 ABRecordRef people = CFArrayGetValueAtIndex(allLinkPeople, i); 56 //獲取當前聯繫人名字 57 NSString*firstName=(__bridge NSString *)(ABRecordCopyValue(people, kABPersonFirstNameProperty)); 58 59 if ([firstName isEqualToString:[_infoDictionary objectForKey:@"name"]]) { 60 isExist = YES; 61 } 62 63 // //獲取當前聯繫人姓氏 64 // NSString*lastName=(__bridge NSString *)(ABRecordCopyValue(people, kABPersonLastNameProperty)); 65 66 //獲取當前聯繫人中間名 67 // NSString*middleName=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonMiddleNameProperty)); 68 // //獲取當前聯繫人的名字首碼 69 // NSString*prefix=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonPrefixProperty)); 70 // //獲取當前聯繫人的名字尾碼 71 // NSString*suffix=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonSuffixProperty)); 72 // //獲取當前聯繫人的昵稱 73 // NSString*nickName=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonNicknameProperty)); 74 // //獲取當前聯繫人的名字拼音 75 // NSString*firstNamePhoneic=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonFirstNamePhoneticProperty)); 76 // //獲取當前聯繫人的姓氏拼音 77 // NSString*lastNamePhoneic=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonLastNamePhoneticProperty)); 78 // //獲取當前聯繫人的中間名拼音 79 // NSString*middleNamePhoneic=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonMiddleNamePhoneticProperty)); 80 // //獲取當前聯繫人的公司 81 // NSString*organization=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonOrganizationProperty)); 82 // //獲取當前聯繫人的職位 83 // NSString*job=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonJobTitleProperty)); 84 // //獲取當前聯繫人的部門 85 // NSString*department=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonDepartmentProperty)); 86 // //獲取當前聯繫人的生日 87 // NSString*birthday=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonBirthdayProperty)); 88 // NSMutableArray * emailArr = [[NSMutableArray alloc]init]; 89 // //獲取當前聯繫人的郵箱 註意是數組 90 // ABMultiValueRef emails= ABRecordCopyValue(people, kABPersonEmailProperty); 91 // for (NSInteger j=0; j<ABMultiValueGetCount(emails); j++) { 92 // [emailArr addObject:(__bridge NSString *)(ABMultiValueCopyValueAtIndex(emails, j))]; 93 // } 94 // //獲取當前聯繫人的備註 95 // NSString*notes=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonNoteProperty)); 96 // //獲取當前聯繫人的電話 數組 97 // NSMutableArray * phoneArr = [[NSMutableArray alloc]init]; 98 // ABMultiValueRef phones= ABRecordCopyValue(people, kABPersonPhoneProperty); 99 // for (NSInteger j=0; j<ABMultiValueGetCount(phones); j++) { 100 // [phoneArr addObject:(__bridge NSString *)(ABMultiValueCopyValueAtIndex(phones, j))]; 101 // } 102 // //獲取創建當前聯繫人的時間 註意是NSDate 103 // NSDate*creatTime=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonCreationDateProperty)); 104 // //獲取最近修改當前聯繫人的時間 105 // NSDate*alterTime=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonModificationDateProperty)); 106 // //獲取地址 107 // ABMultiValueRef address = ABRecordCopyValue(people, kABPersonAddressProperty); 108 // for (int j=0; j<ABMultiValueGetCount(address); j++) { 109 // //地址類型 110 // NSString * type = (__bridge NSString *)(ABMultiValueCopyLabelAtIndex(address, j)); 111 // NSDictionary * temDic = (__bridge NSDictionary *)(ABMultiValueCopyValueAtIndex(address, j)); 112 // //地址字元串,可以按需求格式化 113 // NSString * adress = [NSString stringWithFormat:@"國家:%@\n省:%@\n市:%@\n街道:%@\n郵編:%@",[temDic valueForKey:(NSString*)kABPersonAddressCountryKey],[temDic valueForKey:(NSString*)kABPersonAddressStateKey],[temDic valueForKey:(NSString*)kABPersonAddressCityKey],[temDic valueForKey:(NSString*)kABPersonAddressStreetKey],[temDic valueForKey:(NSString*)kABPersonAddressZIPKey]]; 114 // } 115 // //獲取當前聯繫人頭像圖片 116 // NSData*userImage=(__bridge NSData*)(ABPersonCopyImageData(people)); 117 // //獲取當前聯繫人紀念日 118 // NSMutableArray * dateArr = [[NSMutableArray alloc]init]; 119 // ABMultiValueRef dates= ABRecordCopyValue(people, kABPersonDateProperty); 120 // for (NSInteger j=0; j<ABMultiValueGetCount(dates); j++) { 121 // //獲取紀念日日期 122 // NSDate * data =(__bridge NSDate*)(ABMultiValueCopyValueAtIndex(dates, j)); 123 // //獲取紀念日名稱 124 // NSString * str =(__bridge NSString*)(ABMultiValueCopyLabelAtIndex(dates, j)); 125 // NSDictionary * temDic = [NSDictionary dictionaryWithObject:data forKey:str]; 126 // [dateArr addObject:temDic]; 127 // } 128 } 129 130 131 } 132 //發送一次信號 133 dispatch_semaphore_signal(sema); 134 }); 135 //等待信號觸發 136 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 137 }else{ 138 139 //IOS6之前 140 addBook =ABAddressBookCreate(); 141 142 //獲取所有聯繫人的數組 143 CFArrayRef allLinkPeople = ABAddressBookCopyArrayOfAllPeople(addBook); 144 //獲取聯繫人總數 145 CFIndex number = ABAddressBookGetPersonCount(addBook); 146 //進行遍歷 147 for (NSInteger i=0; i<number; i++) { 148 //獲取聯繫人對象的引用 149 ABRecordRef people = CFArrayGetValueAtIndex(allLinkPeople, i); 150 //獲取當前聯繫人名字 151 NSString*firstName=(__bridge NSString *)(ABRecordCopyValue(people, kABPersonFirstNameProperty)); 152 153 if ([firstName isEqualToString:[_infoDictionary objectForKey:@"name"]]) { 154 isExist = YES; 155 } 156 } 157 } 158 159 if (tip) { 160 //設置提示 161 if (IS_iOS8) { 162 UIAlertController *tipVc = [UIAlertController alertControllerWithTitle:@"友情提示" message:@"請您設置允許APP訪問您的通訊錄\nSettings>General>Privacy" preferredStyle:UIAlertControllerStyleAlert]; 163 UIAlertAction *cancleAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { 164 [self dismissViewControllerAnimated:YES completion:nil]; 165 }]; 166 [tipVc addAction:cancleAction]; 167 [tipVc presentViewController:tipVc animated:YES completion:nil]; 168 }else{ 169 UIAlertView * alart = [[UIAlertView alloc]initWithTitle:@"友情提示" message:@"請您設置允許APP訪問您的通訊錄\nSettings>General>Privacy" delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil, nil]; 170 [alart show]; 171 //非ARC 172 // [alart release]; 173 } 174 } 175 return isExist; 176 } 177 178 //創建新的聯繫人 179 - (void)creatNewRecord 180 { 181 CFErrorRef error = NULL; 182 183 //創建一個通訊錄操作對象 184 ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error); 185 186 //創建一條新的聯繫人紀錄 187 ABRecordRef newRecord = ABPersonCreate(); 188 189 //為新聯繫人記錄添加屬性值 190 ABRecordSetValue(newRecord, kABPersonFirstNameProperty, (__bridge CFTypeRef)[_infoDictionary objectForKey:@"name"], &error); 191 192 //創建一個多值屬性(電話) 193 ABMutableMultiValueRef multi = ABMultiValueCreateMutable(kABMultiStringPropertyType); 194 ABMultiValueAddValueAndLabel(multi, (__bridge CFTypeRef)[_infoDictionary objectForKey:@"phone"], kABPersonPhoneMobileLabel, NULL); 195 ABRecordSetValue(newRecord, kABPersonPhoneProperty, multi, &error); 196 197 //添加email 198 ABMutableMultiValueRef multiEmail = ABMultiValueCreateMutable(kABMultiStringPropertyType); 199 ABMultiValueAddValueAndLabel(multiEmail, (__bridge CFTypeRef)([_infoDictionary objectForKey:@"email"]), kABWorkLabel, NULL); 200 ABRecordSetValue(newRecord, kABPersonEmailProperty, multiEmail, &error); 201 202 203 //添加記錄到通訊錄操作對象 204 ABAddressBookAddRecord(addressBook, newRecord, &error); 205 206 //保存通訊錄操作對象 207 ABAddressBookSave(addressBook, &error); 208 209 //通過此介面訪問系統通訊錄 210 ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { 211 212 if (granted) { 213 //顯示提示 214 if (IS_iOS8) {