通讯录中联系人相关的应用iPhone提供了两个框架:AddressBook.framework和AddressBookUI.framework,使用这两个框架我们可以在程序中访问并显示iPhone数据库中的联系人信息。
- ABAddressBookRef addressBook = nil;
- addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
- //等待同意后向下执行
- dispatch_semaphore_t sema = dispatch_semaphore_create(0);
- ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error)
- {
- dispatch_semaphore_signal(sema);
- });
- dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
- //获取本地通讯录数据库
- ABRecordRef moi=NULL;//联系人
- ABRecordRef annkey=ABPersonCreate();//创建联系人
- //设置联系人的值
- ABRecordSetValue(annkey,kABPersonFirstNameProperty,@"annkey",NULL);
- ABRecordSetValue(annkey,kABPersonLastNameProperty,@"hu",NULL);
- //创建多值属性
- ABMutableMultiValueRef addr=ABMultiValueCreateMutable(kABStringPropertyType);
- //增加属性名和属性值,属性名为kABHomeLabel
- ABMultiValueAddValueAndLabel(addr,@"annkey@qq.con",kABHomeLabel,NULL);
- //设置联系人的多值邮箱属性
- ABRecordSetValue(annkey,kABPersonEmailProperty, addr,NULL);
- ABAddressBookAddRecord(adbk, annkey,NULL);//增加联系人
- ABAddressBookSave(adbk,NULL);//保存联系人
- CFRelease(addr);
- CFRelease(annkey);//,即使是在arc机制里,c对象仍需手动释放
- CFArrayRef sams=ABAddressBookCopyPeopleWithName(adbk, (CFStringRef)@"hu");//联系人数组,可能存在多个同名的联系人,需要通过其他属性来判断具体是哪个
- for (CFIndex ix=0; ix
- // 从联系人数组多个sam中读取
- ABRecordRef sam=CFArrayGetValueAtIndex(sams, ix);
- // 获取联系人的名属性
- CFStringRef last=ABRecordCopyValue(sam,kABPersonLastNameProperty);
- NSLog(@" is find %@",last);
- //找到符合条件的联系人
- if (last&&CFStringCompare(last, (CFStringRef)@"annkey",0)==0) {
- moi=sam;
- }
- if (last) {
- //必须要判断cf对象是否为空,只有不是null才可被释放,如果不判断会报错。
- CFRelease(last); //c对象需手动释放
- }
- }
- if (NULL==moi) {
- //此处通讯录肯定不为空,数据库是存在的
- CFRelease(sams);
- CFRelease(adbk);//c对象需手动释放
- return;
- }
- //获取联系人的邮件属性,初始化为多值
- ABMultiValueRef emails=ABRecordCopyValue(moi,kABPersonEmailProperty);
- if (NULL==emails) {
- NSLog(@"emails is null");
- }
- for (CFIndex ix=0; ix
- //联系人的属性名和属性值
- CFStringRef labe1=ABMultiValueCopyLabelAtIndex(emails, ix);
- CFStringRef value=ABMultiValueCopyValueAtIndex(emails, ix);
- NSLog(@"i have a %@ address I%@",labe1,value);
- CFRelease(labe1);
- CFRelease(value);
- }
- NSLog(@"emails is null2");
- CFRelease(emails);
- CFRelease(sams);
- CFRelease(adbk);
- //获取本地通讯录数据库
- ABRecordRef moi=NULL;//联系人
- ABRecordRef annkey=ABPersonCreate();//创建联系人
- //设置联系人的值
- ABRecordSetValue(annkey,kABPersonFirstNameProperty,@"annkey",NULL);
- ABRecordSetValue(annkey,kABPersonLastNameProperty,@"hu",NULL);
- //创建多值属性
- ABMutableMultiValueRef addr=ABMultiValueCreateMutable(kABStringPropertyType);
- //增加属性名和属性值,属性名为kABHomeLabel
- ABMultiValueAddValueAndLabel(addr,@"annkey@qq.con",kABHomeLabel,NULL);
- //设置联系人的多值邮箱属性
- ABRecordSetValue(annkey,kABPersonEmailProperty, addr,NULL);
- ABAddressBookAddRecord(adbk, annkey,NULL);//增加联系人
- ABAddressBookSave(adbk,NULL);//保存联系人
- CFRelease(addr);
- CFRelease(annkey);//,即使是在arc机制里,c对象仍需手动释放
- CFArrayRef sams=ABAddressBookCopyPeopleWithName(adbk, (CFStringRef)@"hu");//联系人数组,可能存在多个同名的联系人,需要通过其他属性来判断具体是哪个
- for (CFIndex ix=0; ix
- // 从联系人数组多个sam中读取
- ABRecordRef sam=CFArrayGetValueAtIndex(sams, ix);
- // 获取联系人的名属性
- CFStringRef last=ABRecordCopyValue(sam,kABPersonLastNameProperty);
- NSLog(@" is find %@",last);
- //找到符合条件的联系人
- if (last&&CFStringCompare(last, (CFStringRef)@"annkey",0)==0) {
- moi=sam;
- }
- if (last) {
- //必须要判断cf对象是否为空,只有不是null才可被释放,如果不判断会报错。
- CFRelease(last); //c对象需手动释放
- }
- }
- if (NULL==moi) {
- //此处通讯录肯定不为空,数据库是存在的
- CFRelease(sams);
- CFRelease(adbk);//c对象需手动释放
- return;
- }
- //获取联系人的邮件属性,初始化为多值
- ABMultiValueRef emails=ABRecordCopyValue(moi,kABPersonEmailProperty);
- if (NULL==emails) {
- NSLog(@"emails is null");
- }
- for (CFIndex ix=0; ix
- //联系人的属性名和属性值
- CFStringRef labe1=ABMultiValueCopyLabelAtIndex(emails, ix);
- CFStringRef value=ABMultiValueCopyValueAtIndex(emails, ix);
- NSLog(@"i have a %@ address I%@",labe1,value);
- CFRelease(labe1);
- CFRelease(value);
- }
- NSLog(@"emails is null2");
- CFRelease(emails);
- CFRelease(sams);
- CFRelease(adbk);
添加地址簿框架后,我们还需要在工程中添加相应的头文件:
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
1.AddressBookUI显示部分
AddressBookUI中提供了和联系人显示信息相关的一些Controller,有四个:
ABPeoplePickerNavigation
ABPersonViewController:显示一个具体联系人的信息
ABNewPersonViewControlle
ABUnknownPersonViewContr
由于其中最主要的是ABPeoplePickerNavigation
(a)创建并初始化一个ABPeoplePickerNavigation
(b)设置其代理(delegate)
(c)用presentModalViewControll
例子:
- -
(IBAction)showPicker:(id)sender { -
ABPeoplePickerNavigation Controller *picker = -
[[ABPeoplePickerNavigation Controller alloc] init]; -
picker.peoplePickerDelegate = self; -
[self presentModalViewControll er:picker animated:YES]; -
[picker release]; - }
ABPeoplePickerNavigation
(1)
- peoplePickerNavigationCo
ntrollerDidCancel:
当用户选择取消时调用这个方法,可以在这个方法里取消整个通讯录页面的显示。
(2)
- peoplePickerNavigationCo
ntroller:shouldContinueAfterSelec tingPerson:
当用户选择了通讯录中某一个联系人时调用这个方法,可以在这里获取联系人的信息。如果希望可以继续显示这个联系人更具体的信息,则return YES。否则取消整个通讯录页面的显示并return NO。
(3)
- eoplePickerNavigationCon
troller:shouldContinueAfterSelec tingPerson:property:identifier:
如果上一个方法返回的是YES,则会显示某一个联系人信息,如果选择了联系人的某一项纪录,就会调用这个方法,可以通过点击选择联系人的某一项信息。如果希望可以对选择的某一项纪录进行进一步操作,比如直接拨打电话或调用邮箱发送邮件,则return YES。否则取消整个通讯录页面的显示并return NO。
例子:
- -
(void)peoplePickerNavigationCo ntrollerDidCancel:(ABPeoplePickerNavigation Controller *)peoplePicker { - //
assigning control back to the main controller - [picker
dismissModalViewControll erAnimated:YES]; - }
- -
(BOOL)peoplePickerNavigationCo ntroller: (ABPeoplePickerNavigation Controller *)peoplePicker - shouldContinueAfterSelec
tingPerson:(ABRecordRef)person { - //获取联系人姓名
- name.text
= (NSString*)ABRecordCopyCompositeNam e(person); - //获取联系人电话
- ABMutableMultiValueRef
phoneMulti = ABRecordCopyValue(person, kABPersonPhoneProperty); - NSMutableArray
*phones = [[NSMutableArray alloc] init]; - int
i; - for
(i = 0; i < ABMultiValueGetCount(phoneMulti); i++) { - NSString
*aPhone = [(NSString*)ABMultiValueCopyValueAtI ndex(phoneMulti, i) autorelease]; - NSString
*aLabel = [(NSString*)ABMultiValueCopyLabelAtI ndex(phoneMulti, i) autorelease]; - NSLog(@"PhoneLabel:%@
Phone#:%@",aLabel,aPhone); - if([aLabel
isEqualToString:@"_$!<Mobile>!$_"]) - {
- [phones
addObject:aPhone]; - }
- }
- phoneNo.text=@"";
- if([phones
count]>0) - {
- NSString
*mobileNo = [phones objectAtIndex:0]; - phoneNo.text
= mobileNo; - //NSLog(mobileNo);
- }
- //获取联系人邮箱
- ABMutableMultiValueRef
emailMulti = ABRecordCopyValue(person, kABPersonEmailProperty); - NSMutableArray
*emails = [[NSMutableArray alloc] init]; - for
(i = 0;i < ABMultiValueGetCount(emailMulti); i++) - {
- NSString
*emailAdress = [(NSString*)ABMultiValueCopyValueAtI ndex(emailMulti, i) autorelease]; - [emails
addObject:emailAdress]; - }
- email.text=@"";
- if([emails
count]>0) - {
- NSString
*emailFirst=[emails objectAtIndex:0]; - email.text
= emailFirst; - //NSLog(emailFirst);
- }
- [peoplePicker
dismissModalViewControll erAnimated:YES]; - return
NO; - }
- -
(BOOL)peoplePickerNavigationCo ntroller: (ABPeoplePickerNavigation Controller *)peoplePicker -
shouldContinueAfterSelec tingPerson:(ABRecordRef)person - property:(ABPropertyID)property
-
identifier:(ABMultiValueIdentifier)identifier{ - return
NO; - }
2.AddressBook部分
AddressBook框架部分主要是记录联系人的各个信息,ABRecordRef类型的记录既可以代表单个人(kABPersonType),也可以是一个集合(kABGroupType)。
通讯录中联系人的各个属性有两种形式,单值属性和多值属性。单值属性对应的只有一个值,比如联系人的姓名;多值属性对应的可能有多个值,比如联系人有多个电话号码等。
(a)常用方法
- CFTypeRef
ABRecordCopyValue ( -
ABRecordRef record, -
ABPropertyID property - );
从一个记录中获取某个属性对应的值
(b)单值属性对应的方法
- CFStringRef
ABRecordCopyCompositeNam e ( -
ABRecordRef record - );
获取联系人完整的姓名。
(c)多值属性对应的方法
- CFTypeRef
ABMultiValueCopyValueAtI ndex ( -
ABMultiValueRef multiValue, -
CFIndex index - );
返回对应位置处的属性值
- CFStringRef
ABMultiValueCopyLabelAtI ndex ( -
ABMultiValueRef multiValue, -
CFIndex index - );
返回对应位置处的属性标识
- CFArrayRef
ABMultiValueCopyArrayOfA llValues ( -
ABMultiValueRef multiValue - );
返回包含所有属性值的数组
- CFIndex
ABMultiValueGetCount ( -
ABMultiValueRef multiValue - );
返回属性值的个数
例子:
- //获取联系人姓名
- name.text
= (NSString*)ABRecordCopyCompositeNam e(person); - //获取联系人电话
- ABMutableMultiValueRef
phoneMulti = ABRecordCopyValue(person, kABPersonPhoneProperty); - NSMutableArray
*phones = [[NSMutableArray alloc] init]; - int
i; - for
(i = 0; i < ABMultiValueGetCount(phoneMulti); i++) { - NSString
*aPhone = [(NSString*)ABMultiValueCopyValueAtI ndex(phoneMulti, i) autorelease]; - NSString
*aLabel = [(NSString*)ABMultiValueCopyLabelAtI ndex(phoneMulti, i) autorelease]; - NSLog(@"PhoneLabel:%@
Phone#:%@",aLabel,aPhone); - if([aLabel
isEqualToString:@"_$!<Mobile>!$_"]) - {
- [phones
addObject:aPhone]; - }
- }
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
ag:
//选取联系人的方法
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
[self dismissModalViewControllerAnimated:YES];
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
return YES;
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{
NSString* compositeName = (NSString *)ABRecordCopyCompositeName(person);
contactsAdd.Name = compositeName;
nameTextField.text =compositeName;
[compositeName release];
ABMultiValueRef phoneProperty = ABRecordCopyValue(person,property);
NSString *phone = (NSString *)ABMultiValueCopyValueAtIndex(phoneProperty,identifier);
contactsAdd.Phone = (NSString*)phone;
phoneTextField.text= (NSString*)phone;
[self dismissModalViewControllerAnimated:YES];
return NO;
}
............,....,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
IOS编程:Address Book
在IOS中,允许用户对Address Book(地址簿)进行添加、编辑与删除操作。地址簿可以是一些人的集合,也可以是一系列群组的集合。里面的每一个人都有诸如姓氏、名字、电话号码、电子邮件等一系列属性。这些属性可以只有一个值,当然也可以有多个值,列入,一个人的姓氏只能有一个值,而他/她的电话号码却可以有多个值。
IOS SDK中的AddressBook.Framwork框架允许我们与iOS设备的地址簿数据库进行交互,我们可以通过它取得地址簿上所有人的相关信息,也可以对其中的一条或者多条数据进行查询、删除等操作。
为在应用程序中使用地址簿相关的函数,需要将地址簿框架添加到我们的应用程序中:
- 单击Xcode中的工程图标
- 选择欲添加地址簿框架的目标
- 选择屏幕顶部的Build Phases选项卡
- 在Build Phases选项卡中,找到并展开Link Binary选项,单击底部左下角的“+”按钮
- 在弹出的库列表中,选中AddressBook.Framwork,点击添加按钮即可
添加地址簿框架后,我们还需要在工程中添加相应的头文件:#import<AddressBook/AddressBook.h>
查询
要进行地址簿的查询操作,首先要使用 ABAddressBookCreate函数创建一个地址簿数据库的引用,该函数返回一个ABAddressBookRef类型的值,如果地址簿数据库不能访问的话,则返回nil。在进行任何地址簿的操作之前,必须检查改制是否为nil,否者,当应用程序试图去编辑一个空的地址簿是,将会以一个运行时错误退出程序。
在取得地址簿引用后,就可以对地址簿进行查询、编辑等操作了,但需要注意的是,一旦你对地址簿进行任何改变,ABAddressBookHasUnsavedChanges函数将返回一个YES值以告知地址簿发生变化了,此时,你可以使用ABAddressBookSave函数或者ABAddressBookRevert函数来保存或者忽略地址簿的变化。
接下来,调用ABAddressBookCopyArrayOfAllPeople函数来得到地址簿中的所有联系人信息,该函数的返回值是一个CFArrayRef类型的数组。之后遍历该数组,调用ABRecoredCopyValue函数便可得到每个联系人的相关信息。它包含两个参数,第一个参数是地址簿记录应用(ABRecordRef),第二个参数指定了你想要获得何种信息。例如,如果想要查询邮件地址,则第二个参数为kABPersonEmailProperty。当然,如果不想自己创建界面去展示这些内容时,我们还可以使用IOS SDK自带的ABPersonViewController(需要引入AddressBookUI.Framwork框架和添加ABPersonViewControllerDeleagte)来展示和编辑联系人的相关信息。示例代码如下:
ABAddressBookRef abRef = ABAddressBookCreate();
if(abRef != nil){
allarray = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(abRef);
}
CFRelease(abRef);
ABRecordRef person = [allarray objectAtIndex:[indexPath row]];
cell.textLabel.text = [[[NSString alloc] initWithFormat:@”%@%@”, (__bridge_transfer NSString *)ABRecordCopyValue(person,kABPersonFirstNameProperty), (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty)] autorelease];
ABPersonViewController *personView = [[ABPersonViewController alloc]init];
personView.personViewDelegate = self;
personView.displayedPerson = [allarray objectAtIndex:row];
personView.allowsEditing = YES; //是否允许编辑
[self.navigationController pushViewController:personView animated:YES];
[personView release];
编辑
除了调用ABPersonViewController编辑联系人外,还可以使用ABRecordSetValue函数和ABAddressBookAddRecord函数来添加或者修改联系人信息。或者使用IOS SDK自带的ABNewPersonViewController(需要引入AddressBookUI.Framwork框架和添加ABNewPersonViewControllerDeleagte)来添加一个新的联系人,但是别忘记实现相应的代理方法,否则程序会崩溃退出。
ABAddressBookRef abRef = ABAddressBookCreate();
CFErrorRef errorRef = NULL;
ABRecordSetValue(abRef,kABPersonFirstNameProperty,(__bridgeCFTypeRef)@”HamGuy”,&errorRef);
ABRecordSetValue(abRef,kABPersonEmailProperty,(__bridgeCFTypeRef)@”wangrui15@gmail.com”,&errorRef);
ABRecordRef person = [allarray objectAtIndex:[indexPath row]];
ABAddressBookAddRecord(abRef, person, &errorRef);
ABNewPersonViewController *newPersonView = [[ABNewPersonViewControlleralloc] init];
newPersonView.newPersonViewDelegate = self;
UINavigationController *newNavigationController = [[UINavigationControlleralloc]
initWithRootViewController:newPersonView];
[self presentModalViewController:newNavigationController animated:YES];
[newPersonView release];
[newNavigationController release];
-(void) newPersonViewController:(ABNewPersonViewController *)newPersonView didCompleteWithNewPerson:(ABRecordRef)person{
[newPersonView dismissModalViewControllerAnimated:YES];
}
删除
删除联系人使用ABAddressBookRemoveRecord函数来实现,用法与ABAddressBookAddRecord函数类似,不在赘述。如果要清空地址簿的话,可循环调用该方法实现。
ABAddressBookRef abRef = ABAddressBookCreate();
if(abRef == nil)
return;
CFErrorRef errorRef = NULL;
ABAddressBookRemoveRecord(abRef,[allarray objectAtIndex:[indexPathrow]],&errorRef);