公司项目有访问通讯录的需求,所以开始了探索之路。从开始的一无所知,到知识的渐渐清晰。这一切要感谢广大无私分享的 “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 }
这里需要注意的是:
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 }
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier;第一个参数就不用说了,第二个参数 ABRecordRef 这是一个联系人的引用也可以说是一个记录,你可以理解为一个联系人。第三个参数是联系人附带属性的ID,其实ABPropertyID是个int类型值。第四个参数是多值属性的标签。
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:@"1000000000@qq.com" 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) {
215 UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:@"添加成功" message:nil preferredStyle:UIAlertControllerStyleAlert];
216 UIAlertAction *alertAction = [UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
217 [self dismissViewControllerAnimated:YES completion:nil];
218
219 }];
220 [alertVc addAction:alertAction];
221 [self presentViewController:alertVc animated:YES completion:nil];
222 }else{
223
224 UIAlertView *tipView = [[UIAlertView alloc] initWithTitle:nil message:@"添加成功" delegate:self cancelButtonTitle:@"知道了" otherButtonTitles:nil, nil];
225 [tipView show];
226 //非ARC
227 // [tipView release];
228 }
229 }
230 });
231
232 CFRelease(multiEmail);
233 CFRelease(multi);
234 CFRelease(newRecord);
235 CFRelease(addressBook);
236 }
代码中有每个步骤都有对应的注释,对应看起来会容易一些!下面是效果图:
如果需要添加联系人的其他属性,方法类似,只是属性名不同。慢慢挖掘吧,伙伴们!
声明:此文仅为了记录本人开发中的遇到并解决的问题,权当是一篇笔记,并不是教学blog,不免会有错误,如有烦请指正,大家共同学习!谢谢!