通讯录
AddressBook
iOS中帶有一個Contacts應用程序來管理聯系人,但是有些時候我們希望自己的應用能夠訪問或者修改這些信息,這個時候就要用到AddressBook.framework框架。iOS中的通訊錄是存儲在數據庫中的,由于iOS的權限設計,開發人員是不允許直接訪問通訊錄數據庫的,必須依靠AddressBook提供的標準API來實現通訊錄操作。通過AddressBook.framework開發者可以從底層去操作AddressBook.framework的所有信息,但是需要注意的是這個框架是基于C語言編寫的,無法使用ARC來管理內存,開發者需要自己管理內存。下面大致介紹一下通訊錄操作中常用的類型:
- ABAddressBookRef:代表通訊錄對象,通過該對象開發人員不用過多的關注通訊錄的存儲方式,可以直接以透明的方式去訪問、保存(在使用AddressBook.framework操作聯系人時,所有的增加、刪除、修改后都必須執行保存操作,類似于Core Data)等。?
- ABRecordRef:代表一個通用的記錄對象,可以是一條聯系人信息,也可以是一個群組,可以通過ABRecordGetRecordType()函數獲得具體類型。如果作為聯系人(事實上也經常使用它作為聯系人),那么這個記錄記錄了一個完整的聯系人信息(姓名、性別、電話、郵件等),每條記錄都有一個唯一的ID標示這條記錄(可以通過ABRecordGetRecordID()函數獲得)。?
- ABPersonRef:代表聯系人信息,很少直接使用,實際開發過程中通常會使用類型為“kABPersonType”的ABRecordRef來表示聯系人(由此可見ABPersonRef其實是一種類型為“kABPersonType”的ABRecordRef)?
- ABGroupRef:代表群組,與ABPersonRef類似,很少直接使用ABGroupRef,而是使用類型為“kABGroupType”的ABRecordRef來表示群組,一個群組可以包含多個聯系人,一個聯系人也同樣可以多個群組。
由于通訊錄操作的關鍵是對ABRecordRef的操作,首先看一下常用的操作通訊錄記錄的方法:
ABPersonCreate():創建一個類型為“kABPersonType”的ABRecordRef。
ABRecordCopyValue():取得指定屬性的值。
ABRecordCopyCompositeName():取得聯系人(或群組)的復合信息(對于聯系人則包括:姓、名、公司等信息,對于群組則返回組名稱)。
ABRecordSetValue():設置ABRecordRef的屬性值。注意在設置ABRecordRef的值時又分為單值屬性和多值屬性:單值屬性設置只要通過ABRecordSetValue()方法指定屬性名和值即可;多值屬性則要先通過創建一個ABMutableMultiValueRef類型的變量,然后通過ABMultiValueAddValueAndLabel()方法依次添加屬性值,最后通過ABRecordSetValue()方法將ABMutableMultiValueRef類型的變量設置為記錄值。
ABRecordRemoveValue():刪除指定的屬性值。
注意:
由于聯系人訪問時(讀取、設置、刪除時)牽扯到大量聯系人屬性,可以到ABPerson.h中查詢或者直接到幫助文檔“Personal Information Properties”
通訊錄的訪問步驟一般如下:
下面就通過一個示例演示一下如何通過ABAddressBook.framework訪問通訊錄,這個例子中通過一個UITableViewController模擬一下通訊錄的查看、刪除、添加操作。
主控制器視圖,用于顯示聯系人,修改刪除聯系人:
KCContactViewController.h
#import <UIKit/UIKit.h>/*** 定義一個協議作為代理*/ @protocol KCContactDelegate //新增或修改聯系人 -(void)editPersonWithFirstName:(NSString *)firstName lastName:(NSString *)lastName workNumber:(NSString *)workNumber; //取消修改或新增 -(void)cancelEdit; @end@interface KCContactTableViewController : UITableViewController@endKCContactViewController.m
#import "KCContactTableViewController.h" #import <AddressBook/AddressBook.h> #import "KCAddPersonViewController.h"@interface KCContactTableViewController ()<KCContactDelegate>@property (assign,nonatomic) ABAddressBookRef addressBook;//通訊錄 @property (strong,nonatomic) NSMutableArray *allPerson;//通訊錄所有人員@property (assign,nonatomic) int isModify;//標識是修改還是新增,通過選擇cell進行導航則認為是修改,否則視為新增 @property (assign,nonatomic) UITableViewCell *selectedCell;//當前選中的單元格@end@implementation KCContactTableViewController#pragma mark - 控制器視圖 - (void)viewDidLoad {[super viewDidLoad];//請求訪問通訊錄并初始化數據[self requestAddressBook]; }//由于在整個視圖控制器周期內addressBook都駐留在內存中,所有當控制器視圖銷毀時銷毀該對象 -(void)dealloc{if (self.addressBook!=NULL) {CFRelease(self.addressBook);} }#pragma mark - UI事件 //點擊刪除按鈕 - (IBAction)trashClick:(UIBarButtonItem *)sender {self.tableView.editing=!self.tableView.editing; }#pragma mark - UITableView數據源方法- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {return 1; }- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {return self.allPerson.count; }- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {static NSString *identtityKey=@"myTableViewCellIdentityKey1";UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:identtityKey];if(cell==nil){cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identtityKey];}//取得一條人員記錄ABRecordRef recordRef=(__bridge ABRecordRef)self.allPerson[indexPath.row];//取得記錄中得信息NSString *firstName=(__bridge NSString *) ABRecordCopyValue(recordRef, kABPersonFirstNameProperty);//注意這里進行了強轉,不用自己釋放資源NSString *lastName=(__bridge NSString *)ABRecordCopyValue(recordRef, kABPersonLastNameProperty);ABMultiValueRef phoneNumbersRef= ABRecordCopyValue(recordRef, kABPersonPhoneProperty);//獲取手機號,注意手機號是ABMultiValueRef類,有可能有多條 // NSArray *phoneNumbers=(__bridge NSArray *)ABMultiValueCopyArrayOfAllValues(phoneNumbersRef);//取得CFArraryRef類型的手機記錄并轉化為NSArrarylong count= ABMultiValueGetCount(phoneNumbersRef); // for(int i=0;i<count;++i){ // NSString *phoneLabel= (__bridge NSString *)(ABMultiValueCopyLabelAtIndex(phoneNumbersRef, i)); // NSString *phoneNumber=(__bridge NSString *)(ABMultiValueCopyValueAtIndex(phoneNumbersRef, i)); // NSLog(@"%@:%@",phoneLabel,phoneNumber); // }cell.textLabel.text=[NSString stringWithFormat:@"%@ %@",firstName,lastName];if (count>0) {cell.detailTextLabel.text=(__bridge NSString *)(ABMultiValueCopyValueAtIndex(phoneNumbersRef, 0));}if(ABPersonHasImageData(recordRef)){//如果有照片數據NSData *imageData= (__bridge NSData *)(ABPersonCopyImageData(recordRef));cell.imageView.image=[UIImage imageWithData:imageData];}else{cell.imageView.image=[UIImage imageNamed:@"avatar"];//沒有圖片使用默認頭像}//使用cell的tag存儲記錄idcell.tag=ABRecordGetRecordID(recordRef);return cell; }- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {if (editingStyle == UITableViewCellEditingStyleDelete) {ABRecordRef recordRef=(__bridge ABRecordRef )self.allPerson[indexPath.row];[self removePersonWithRecord:recordRef];//從通訊錄刪除[self.allPerson removeObjectAtIndex:indexPath.row];//從數組移除[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];//從列表刪除} else if (editingStyle == UITableViewCellEditingStyleInsert) {// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view} }#pragma mark - UITableView代理方法 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{self.isModify=1;self.selectedCell=[tableView cellForRowAtIndexPath:indexPath];[self performSegueWithIdentifier:@"AddPerson" sender:self]; }#pragma mark - Navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {if([segue.identifier isEqualToString:@"AddPerson"]){UINavigationController *navigationController=(UINavigationController *)segue.destinationViewController;//根據導航控制器取得添加/修改人員的控制器視圖KCAddPersonViewController *addPersonController=(KCAddPersonViewController *)navigationController.topViewController;addPersonController.delegate=self;//如果是通過選擇cell進行的導航操作說明是修改,否則為添加if (self.isModify) {UITableViewCell *cell=self.selectedCell;addPersonController.recordID=(ABRecordID)cell.tag;//設置NSArray *array=[cell.textLabel.text componentsSeparatedByString:@" "];if (array.count>0) {addPersonController.firstNameText=[array firstObject];}if (array.count>1) {addPersonController.lastNameText=[array lastObject];}addPersonController.workPhoneText=cell.detailTextLabel.text;}} }#pragma mark - KCContact代理方法 -(void)editPersonWithFirstName:(NSString *)firstName lastName:(NSString *)lastName workNumber:(NSString *)workNumber{if (self.isModify) {UITableViewCell *cell=self.selectedCell;NSIndexPath *indexPath= [self.tableView indexPathForCell:cell];[self modifyPersonWithRecordID:(ABRecordID)cell.tag firstName:firstName lastName:lastName workNumber:workNumber];[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight];}else{[self addPersonWithFirstName:firstName lastName:lastName workNumber:workNumber];//通訊簿中添加信息[self initAllPerson];//重新初始化數據[self.tableView reloadData];}self.isModify=0; } -(void)cancelEdit{self.isModify=0; }#pragma mark - 私有方法 /*** 請求訪問通訊錄*/ -(void)requestAddressBook{//創建通訊錄對象self.addressBook=ABAddressBookCreateWithOptions(NULL, NULL);//請求訪問用戶通訊錄,注意無論成功與否block都會調用ABAddressBookRequestAccessWithCompletion(self.addressBook, ^(bool granted, CFErrorRef error) {if (!granted) {NSLog(@"未獲得通訊錄訪問權限!");}[self initAllPerson];}); } /*** 取得所有通訊錄記錄*/ -(void)initAllPerson{//取得通訊錄訪問授權ABAuthorizationStatus authorization= ABAddressBookGetAuthorizationStatus();//如果未獲得授權if (authorization!=kABAuthorizationStatusAuthorized) {NSLog(@"尚未獲得通訊錄訪問授權!");return ;}//取得通訊錄中所有人員記錄CFArrayRef allPeople= ABAddressBookCopyArrayOfAllPeople(self.addressBook);self.allPerson=(__bridge NSMutableArray *)allPeople;//釋放資源CFRelease(allPeople);}/*** 刪除指定的記錄** @param recordRef 要刪除的記錄*/ -(void)removePersonWithRecord:(ABRecordRef)recordRef{ABAddressBookRemoveRecord(self.addressBook, recordRef, NULL);//刪除ABAddressBookSave(self.addressBook, NULL);//刪除之后提交更改 } /*** 根據姓名刪除記錄*/ -(void)removePersonWithName:(NSString *)personName{CFStringRef personNameRef=(__bridge CFStringRef)(personName);CFArrayRef recordsRef= ABAddressBookCopyPeopleWithName(self.addressBook, personNameRef);//根據人員姓名查找CFIndex count= CFArrayGetCount(recordsRef);//取得記錄數for (CFIndex i=0; i<count; ++i) {ABRecordRef recordRef=CFArrayGetValueAtIndex(recordsRef, i);//取得指定的記錄ABAddressBookRemoveRecord(self.addressBook, recordRef, NULL);//刪除}ABAddressBookSave(self.addressBook, NULL);//刪除之后提交更改CFRelease(recordsRef); }/*** 添加一條記錄** @param firstName 名* @param lastName 姓* @param iPhoneName iPhone手機號*/ -(void)addPersonWithFirstName:(NSString *)firstName lastName:(NSString *)lastName workNumber:(NSString *)workNumber{//創建一條記錄ABRecordRef recordRef= ABPersonCreate();ABRecordSetValue(recordRef, kABPersonFirstNameProperty, (__bridge CFTypeRef)(firstName), NULL);//添加名ABRecordSetValue(recordRef, kABPersonLastNameProperty, (__bridge CFTypeRef)(lastName), NULL);//添加姓ABMutableMultiValueRef multiValueRef =ABMultiValueCreateMutable(kABStringPropertyType);//添加設置多值屬性ABMultiValueAddValueAndLabel(multiValueRef, (__bridge CFStringRef)(workNumber), kABWorkLabel, NULL);//添加工作電話ABRecordSetValue(recordRef, kABPersonPhoneProperty, multiValueRef, NULL);//添加記錄ABAddressBookAddRecord(self.addressBook, recordRef, NULL);//保存通訊錄,提交更改ABAddressBookSave(self.addressBook, NULL);//釋放資源CFRelease(recordRef);CFRelease(multiValueRef); }/*** 根據RecordID修改聯系人信息** @param recordID 記錄唯一ID* @param firstName 姓* @param lastName 名* @param homeNumber 工作電話*/ -(void)modifyPersonWithRecordID:(ABRecordID)recordID firstName:(NSString *)firstName lastName:(NSString *)lastName workNumber:(NSString *)workNumber{ABRecordRef recordRef=ABAddressBookGetPersonWithRecordID(self.addressBook,recordID);ABRecordSetValue(recordRef, kABPersonFirstNameProperty, (__bridge CFTypeRef)(firstName), NULL);//添加名ABRecordSetValue(recordRef, kABPersonLastNameProperty, (__bridge CFTypeRef)(lastName), NULL);//添加姓ABMutableMultiValueRef multiValueRef =ABMultiValueCreateMutable(kABStringPropertyType);ABMultiValueAddValueAndLabel(multiValueRef, (__bridge CFStringRef)(workNumber), kABWorkLabel, NULL);ABRecordSetValue(recordRef, kABPersonPhoneProperty, multiValueRef, NULL);//保存記錄,提交更改ABAddressBookSave(self.addressBook, NULL);//釋放資源CFRelease(multiValueRef); } @end新增或修改控制器視圖,用于顯示一個聯系人的信息或者新增一個聯系人:
KCAddPersonViewController.h
#import <UIKit/UIKit.h> @protocol KCContactDelegate;@interface KCAddPersonViewController : UIViewController@property (assign,nonatomic) int recordID;//通訊錄記錄id,如果ID不為0則代表修改否則認為是新增 @property (strong,nonatomic) NSString *firstNameText; @property (strong,nonatomic) NSString *lastNameText; @property (strong,nonatomic) NSString *workPhoneText;@property (strong,nonatomic) id<KCContactDelegate> delegate;@endKCAddPersonViewController.m
#import "KCAddPersonViewController.h" #import "KCContactTableViewController.h"@interface KCAddPersonViewController ()@property (weak, nonatomic) IBOutlet UITextField *firstName; @property (weak, nonatomic) IBOutlet UITextField *lastName; @property (weak, nonatomic) IBOutlet UITextField *workPhone; @end@implementation KCAddPersonViewController- (void)viewDidLoad {[super viewDidLoad];[self setupUI]; }#pragma mark - UI事件 - (IBAction)cancelClick:(UIBarButtonItem *)sender {[self.delegate cancelEdit];[self dismissViewControllerAnimated:YES completion:nil]; }- (IBAction)doneClick:(UIBarButtonItem *)sender {//調用代理方法[self.delegate editPersonWithFirstName:self.firstName.text lastName:self.lastName.text workNumber:self.workPhone.text];[self dismissViewControllerAnimated:YES completion:nil]; }#pragma mark - 私有方法 -(void)setupUI{if (self.recordID) {//如果ID不為0則認為是修改,此時需要初始化界面self.firstName.text=self.firstNameText;self.lastName.text=self.lastNameText;self.workPhone.text=self.workPhoneText;} } @end運行效果:
備注:
1.上文中所指的以Ref結尾的對象事實上是該對象的指針(或引用),在C語言的框架中多數類型會以Ref結尾,這個類型本身就是一個指針,定義時不需要加“*”。
2.通常方法中包含copy、create、new、retain等關鍵字的方法創建的變量使用之后需要調用對應的release方法釋放。例如:使用ABPersonCreate();創建完ABRecordRef變量后使用CFRelease()方法釋放。
3.在與很多C語言框架交互時可以都存在Obj-C和C語言類型之間的轉化(特別是Obj-C和Core Foundation框架中的一些轉化),此時可能會用到橋接,只要在強轉之后前面加上”__bridge”即可,經過橋接轉化后的類型不需要再去手動維護內存,也就不需要使用對應的release方法釋放內存。
4.AddressBook框架中很多類型的創建、屬性設置等都是以這個類型名開發頭的方法來創建的,事實上如果大家熟悉了其他框架會發現也都是類似的,這是Apple開發中約定俗成的命名規則(特別是C語言框架)。例如:要給ABRecordRef類型的變量設置屬性則可以通過ABRecordSetValue()方法完成。
AddressBookUI
使用AddressBook.framework來操作通訊錄特點就是可以對通訊錄有更加精確的控制,但是缺點就是面對大量C語言API稍嫌麻煩,于是Apple官方提供了另一套框架供開發者使用,那就是AddressBookUI.framework。例如前面查看、新增、修改人員的界面這個框架就提供了現成的控制器視圖供開發者使用。下面是這個框架中提供的控制器視圖:
- ABPersonViewController:用于查看聯系人信息(可設置編輯)。需要設置displayedPerson屬性來設置要顯示或編輯的聯系人。?
- ABNewPersonViewController:用于新增聯系人信息。?
- ABUnknownPersonViewController:用于顯示一個未知聯系人(尚未保存的聯系人)信息。需要設置displayedPerson屬性來設置要顯示的未知聯系人。
以上三個控制器視圖均繼承于UIViewController,在使用過程中必須使用一個UINavigationController進行包裝,否則只能看到視圖內容無法進行操作(例如對于ABNewPersonViewController如果不使用UINavigationController進行包裝則沒有新增和取消按鈕),同時注意包裝后的控制器視圖不需要處理具體新增、修改邏輯(增加和修改的處理邏輯對應的控制器視圖內部已經完成),但是必須處理控制器的關閉操作(調用dismissViewControllerAnimated::方法),并且可以通過代理方法獲得新增、修改的聯系人。下面看一下三個控制器視圖的代理方法:
1.ABPersonViewController的displayViewDelegate代理方法:
-(BOOL)personViewController:(ABPersonViewController *)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier:此方法會在選擇了一個聯系人屬性后觸發,四個參數分別代表:使用的控制器視圖、所查看的聯系人、所選則的聯系人屬性、該屬性是否是多值屬性。
2.ABNewPersonViewController的newPersonViewDelegate代理方法:
-(void)newPersonViewController:(ABNewPersonViewController *)newPersonView didCompleteWithNewPerson:(ABRecordRef)person:點擊取消或完成后觸發,如果參數中的person為NULL說明點擊了取消,否則說明點擊了完成。無論是取消還是完成操作,此方法調用時保存操作已經進行完畢,不需要在此方法中自己保存聯系人信息。
3.ABUnkownPersonViewcontroller的unkownPersonViewDelegate代理方法:
-(void)unknownPersonViewController:(ABUnknownPersonViewController *)unknownCardViewController didResolveToPerson:(ABRecordRef)person:保存此聯系人時調用,調用后將此聯系人返回。
-(BOOL)unknownPersonViewController:(ABUnknownPersonViewController *)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier:選擇一個位置聯系人屬性之后執行,返回值代表是否執行默認的選擇操作(例如如果是手機號,默認操作會撥打此電話)
除了上面三類控制器視圖在AddressBookUI中還提供了另外一個控制器視圖ABPeoplePickerNavigationController,它與之前介紹的UIImagePickerController、MPMediaPickerController類似,只是他是用來選擇一個聯系人的。這個控制器視圖本身繼承于UINavigationController,視圖自身的“組”、“取消”按鈕操作不需要開發者來完成(例如開發者不用在點擊取消是關閉當前控制器視圖,它自身已經實現了關閉方法),當然這里主要說一下這個控制器視圖的peoplePickerDelegate代理方法:
-(void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person:選擇一個聯系人后執行。此代理方法實現后代理方法“-(void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier”不會再執行。并且一旦實現了這個代理方法用戶只能選擇到聯系人視圖,無法查看具體聯系人的信息。
-(void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker:用戶點擊取消后執行。
-(void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier:選擇聯系人具體的屬性后執行,注意如果要執行此方法則不能實現-(void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person代理方法,此時如果點擊一個具體聯系人會導航到聯系人詳細信息界面,用戶點擊具體的屬性后觸發此方法。
下面就看一下上面四個控制器視圖的使用方法,在下面的程序中定義了四個按鈕,點擊不同的按鈕調用不同的控制器視圖用于演示:
// // ViewController.m // AddressBookUI // // Created by Kenshin Cui on 14/04/05. // Copyright (c) 2014年 cmjstudio. All rights reserved. //#import "ViewController.h" #import <AddressBookUI/AddressBookUI.h>@interface ViewController ()<ABNewPersonViewControllerDelegate,ABUnknownPersonViewControllerDelegate,ABPeoplePickerNavigationControllerDelegate,ABPersonViewControllerDelegate>@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad]; }#pragma mark - UI事件 //添加聯系人 - (IBAction)addPersonClick:(UIButton *)sender {ABNewPersonViewController *newPersonController=[[ABNewPersonViewController alloc]init];//設置代理newPersonController.newPersonViewDelegate=self;//注意ABNewPersonViewController必須包裝一層UINavigationController才能使用,否則不會出現取消和完成按鈕,無法進行保存等操作UINavigationController *navigationController=[[UINavigationController alloc]initWithRootViewController:newPersonController];[self presentViewController:navigationController animated:YES completion:nil]; } // - (IBAction)unknownPersonClick:(UIButton *)sender {ABUnknownPersonViewController *unknownPersonController=[[ABUnknownPersonViewController alloc]init];//設置未知人員ABRecordRef recordRef=ABPersonCreate();ABRecordSetValue(recordRef, kABPersonFirstNameProperty, @"Kenshin", NULL);ABRecordSetValue(recordRef, kABPersonLastNameProperty, @"Cui", NULL);ABMultiValueRef multiValueRef=ABMultiValueCreateMutable(kABStringPropertyType);ABMultiValueAddValueAndLabel(multiValueRef, @"18500138888", kABHomeLabel, NULL);ABRecordSetValue(recordRef, kABPersonPhoneProperty, multiValueRef, NULL);unknownPersonController.displayedPerson=recordRef;//設置代理unknownPersonController.unknownPersonViewDelegate=self;//設置其他屬性unknownPersonController.allowsActions=YES;//顯示標準操作按鈕unknownPersonController.allowsAddingToAddressBook=YES;//是否允許將聯系人添加到地址簿CFRelease(multiValueRef);CFRelease(recordRef);//使用導航控制器包裝UINavigationController *navigationController=[[UINavigationController alloc]initWithRootViewController:unknownPersonController];[self presentViewController:navigationController animated:YES completion:nil]; } - (IBAction)showPersonClick:(UIButton *)sender {ABPersonViewController *personController=[[ABPersonViewController alloc]init];//設置聯系人ABAddressBookRef addressBook=ABAddressBookCreateWithOptions(NULL, NULL);ABRecordRef recordRef= ABAddressBookGetPersonWithRecordID(addressBook, 1);//取得id為1的聯系人記錄personController.displayedPerson=recordRef;//設置代理personController.personViewDelegate=self;//設置其他屬性personController.allowsActions=YES;//是否顯示發送信息、共享聯系人等按鈕personController.allowsEditing=YES;//允許編輯 // personController.displayedProperties=@[@(kABPersonFirstNameProperty),@(kABPersonLastNameProperty)];//顯示的聯系人屬性信息,默認顯示所有信息//使用導航控制器包裝UINavigationController *navigationController=[[UINavigationController alloc]initWithRootViewController:personController];[self presentViewController:navigationController animated:YES completion:nil]; }- (IBAction)selectPersonClick:(UIButton *)sender {ABPeoplePickerNavigationController *peoplePickerController=[[ABPeoplePickerNavigationController alloc]init];//設置代理peoplePickerController.peoplePickerDelegate=self;[self presentViewController:peoplePickerController animated:YES completion:nil]; }#pragma mark - ABNewPersonViewController代理方法 //完成新增(點擊取消和完成按鈕時調用),注意這里不用做實際的通訊錄增加工作,此代理方法調用時已經完成新增,當保存成功的時候參數中得person會返回保存的記錄,如果點擊取消person為NULL -(void)newPersonViewController:(ABNewPersonViewController *)newPersonView didCompleteWithNewPerson:(ABRecordRef)person{//如果有聯系人信息if (person) {NSLog(@"%@ 信息保存成功.",(__bridge NSString *)(ABRecordCopyCompositeName(person)));}else{NSLog(@"點擊了取消.");}//關閉模態視圖窗口[self dismissViewControllerAnimated:YES completion:nil];} #pragma mark - ABUnknownPersonViewController代理方法 //保存未知聯系人時觸發 -(void)unknownPersonViewController:(ABUnknownPersonViewController *)unknownCardViewController didResolveToPerson:(ABRecordRef)person{if (person) {NSLog(@"%@ 信息保存成功!",(__bridge NSString *)(ABRecordCopyCompositeName(person)));}[self dismissViewControllerAnimated:YES completion:nil]; } //選擇一個人員屬性后觸發,返回值YES表示觸發默認行為操作,否則執行代理中自定義的操作 -(BOOL)unknownPersonViewController:(ABUnknownPersonViewController *)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{if (person) {NSLog(@"選擇了屬性:%i,值:%@.",property,(__bridge NSString *)ABRecordCopyValue(person, property));}return NO; } #pragma mark - ABPersonViewController代理方法 //選擇一個人員屬性后觸發,返回值YES表示觸發默認行為操作,否則執行代理中自定義的操作 -(BOOL)personViewController:(ABPersonViewController *)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{if (person) {NSLog(@"選擇了屬性:%i,值:%@.",property,(__bridge NSString *)ABRecordCopyValue(person, property));}return NO; } #pragma mark - ABPeoplePickerNavigationController代理方法 //選擇一個聯系人后,注意這個代理方法實現后屬性選擇的方法將不會再調用 -(void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person{if (person) {NSLog(@"選擇了%@.",(__bridge NSString *)(ABRecordCopyCompositeName(person)));} } //選擇屬性之后,注意如果上面的代理方法實現后此方法不會被調用 //-(void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{ // if (person && property) { // NSLog(@"選擇了屬性:%i,值:%@.",property,(__bridge NSString *)ABRecordCopyValue(person, property)); // } //} //點擊取消按鈕 -(void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker{NSLog(@"取消選擇."); } @end運行效果:
?????
?????
注意:
為了讓大家可以更加清楚的看到幾個控制器視圖的使用,這里并沒有結合前面的UITableViewController來使用,事實上大家結合前面UITableViewController可以做一個完善的通訊錄應用。
總結
- 上一篇: 有1~5000一组乱序数列,请使用伪代码
- 下一篇: bash 快捷键