iOS學習筆記29-系統(tǒng)服務(二)通訊錄

一、通訊錄

iOS中的通訊錄是存儲在數(shù)據(jù)庫中的姥闪,由于iOS的權(quán)限設計筐喳,開發(fā)人員是不允許直接訪問通訊錄數(shù)據(jù)庫的,實現(xiàn)通訊錄操作需要使用到AddressBook.framework框架函喉。

AddressBook.framework框架:
  • 可以從底層去操作通訊錄的所有信息避归,做到精確控制
  • 是基于C語言編寫的,無法使用ARC管理內(nèi)存管呵,需要開發(fā)者手動管理內(nèi)存
  • 需要自構(gòu)UI界面

iOS還提供了另外一個框架來供開發(fā)者操作通訊錄梳毙,那就是AddressBookUI.framework

AddressBookUI.framework框架:
  • 該框架封裝AddressBook.framework,向外提供現(xiàn)成視圖控制器使用
  • 可以使用ARC管理內(nèi)存
  • 高度封裝化捐下,界面固定,可定制性差

這兩個框架各有各的優(yōu)點坷襟,各有各的缺點奸柬,具體采用哪一種去操作通訊錄看具體需求決定。

二啤握、AddressBook

AddressBook.framework框架是基于C語言的鸟缕,缺少面向?qū)ο蟮乃枷耄晕覀兛梢园牙锩嬉恍┙Y(jié)構(gòu)體理解為一個“類”

首先我們來了解幾個核心結(jié)構(gòu)體:
  1. ABAddressBookRef
    通訊錄對象排抬,全局管理通訊錄操作懂从,比如修改保存等
  1. ABRecordRef
    通用的記錄對象,可以是一條聯(lián)系人信息蹲蒲,也可以是一個群組番甩,通過具體類型進行區(qū)分,每條記錄都有一個唯一ID標識
  2. ABPersonRef
    聯(lián)系人信息届搁,不常用缘薛,可以用類型為kABPersonTypeABRecordRef代替窍育。
  3. ABGroupRef
    群組信息,不常用宴胧,可以用類型為kABGroupTypeABRecordRef代替漱抓。
常使用到關于記錄Record的C語言函數(shù):
/* 獲取一條記錄對象的唯一標識ID */
ABRecordID ABRecordGetRecordID(ABRecordRef record);
/* 創(chuàng)建一條記錄對象,類型為kABPersonType恕齐,表示一條聯(lián)系人信息 */
ABRecordRef ABPersonCreate(void);
/* 創(chuàng)建一條記錄對象乞娄,類型為kABGroupType,表示一條群組信息 */
ABRecordRef ABGroupCreate(void);
/* 獲取指定屬性的值 */
CFTypeRef ABRecordCopyValue(ABRecordRef record, ABPropertyID property);
/* 設置紀錄的屬性值显歧,返回設置是否成功 */
bool ABRecordSetValue(
    ABRecordRef record, /* 記錄 */
    ABPropertyID property, /* 屬性 */
    CFTypeRef value, /* 值仪或,可以是單值,也可以是多重值 */
    CFErrorRef* error /* 錯誤信息 */
);
/* 向多重值添加單值 */
bool ABMultiValueAddValueAndLabel(
    ABMutableMultiValueRef multiValue, /* 多重值 */
    CFTypeRef value, /* 單值 */
    CFStringRef label, /* 單值對應的屬性名 */
    ABMultiValueIdentifier *outIdentifier /* 多重值的標示 */
);
/* 從多重值中取出指定索引的單值 */
CFTypeRef ABMultiValueCopyValueAtIndex(
    ABMultiValueRef multiValue, 
    CFIndex index
);
/* 刪除指定的屬性值 */
bool ABRecordRemoveValue(
    ABRecordRef record, /* 記錄 */
    ABPropertyID property, /* 屬性 */
    CFErrorRef* error /* 錯誤信息 */
);
常使用到的通訊錄操作的函數(shù)
/* 創(chuàng)建通訊錄對象 */
ABAddressBookRef ABAddressBookCreate(void);
/* 操作通訊錄用戶授權(quán),注意無論成功與否回調(diào)都會調(diào)用 */
void ABAddressBookRequestAccessWithCompletion(
    ABAddressBookRef addressBook,  /* 通訊錄 */
    ABAddressBookRequestAccessCompletionHandler completion /* 回調(diào) */
);
/* 獲取通訊錄所有的記錄 */
CFArrayRef ABAddressBookCopyArrayOfAllPeople(ABAddressBookRef addressBook);
/* 添加記錄進通訊錄 */
bool ABAddressBookAddRecord(
    ABAddressBookRef addressBook, /* 通訊錄 */
    ABRecordRef record, /* 記錄 */
    CFErrorRef* error /* 錯誤信息 */
);
/* 從通訊錄刪除記錄 */
bool ABAddressBookRemoveRecord(
    ABAddressBookRef addressBook,/* 通訊錄 */
    ABRecordRef record, /* 記錄 */
    CFErrorRef* error/* 錯誤信息 */
);
/* 從通訊錄中獲取一個記錄士骤,根據(jù)記錄ID */
ABRecordRef ABAddressBookGetPersonWithRecordID(
    ABAddressBookRef addressBook, /* 通訊錄 */
    ABRecordID recordID /* 記錄ID */
);
/* 保持通訊錄范删,修改了通訊錄需要保存提交修改 */
bool ABAddressBookSave(
    ABAddressBookRef addressBook, /* 通訊錄 */
    CFErrorRef* error /* 錯誤信息 */
);
通訊錄使用步驟:
  1. 創(chuàng)建通訊錄對象ABAddressBookRef
  1. 請求用戶授權(quán)操作通訊錄ABAddressBookRequestAccessWithCompletion
  2. 查詢所有通訊錄的記錄ABAddressBookCopyArrayOfAllPeople
  3. 添加記錄,刪除記錄拷肌,修改記錄
  4. 修改通訊錄后到旦,記住要通訊錄保存ABAddressBookSave
下面是實際代碼:
1. 創(chuàng)建通訊錄并請求授權(quán)
/* 請求訪問通訊錄并獲取通訊錄所有記錄 */
- (void)requestAddressBook{
    //創(chuàng)建通訊錄對象
    self.addressBook = ABAddressBookCreate();
    
    //請求訪問用戶通訊錄,注意無論成功與否block都會調(diào)用
    ABAddressBookRequestAccessWithCompletion(self.addressBook, ^(bool granted, CFErrorRef error) {
        if (!granted) {
            NSLog(@"未獲得通訊錄訪問權(quán)限!");
        }
        //獲取所有通訊錄記錄
        [self initAllPerson];
        //刷新表格
        [self.tableView reloadData];
    });
}

/* 取得所有通訊錄記錄 */
- (void)initAllPerson{
    //取得通訊錄訪問授權(quán)
    ABAuthorizationStatus authorization = ABAddressBookGetAuthorizationStatus();
    //如果未獲得授權(quán)
    if (authorization != kABAuthorizationStatusAuthorized) {
        NSLog(@"尚未獲得通訊錄訪問授權(quán)廓块!");
        return ;
    }
    //取得通訊錄中所有人員記錄
    CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(self.addressBook);
    self.allPerson = (__bridge NSMutableArray *)allPeople;
    //釋放資源
    CFRelease(allPeople);
}
2. 添加聯(lián)系人

/**
 *  添加一條記錄
 *
 *  @param firstName  名
 *  @param lastName   姓
 *  @param iPhoneName iPhone手機號
 */
- (void)addPersonWithFirstName:(NSString *)firstName
                      lastName:(NSString *)lastName
                    workNumber:(NSString *)workNumber
{
    //創(chuàng)建一條記錄
    ABRecordRef recordRef = ABPersonCreate();
    //添加名
    ABRecordSetValue(recordRef,kABPersonFirstNameProperty,(__bridge CFTypeRef)(firstName),NULL);
    //添加姓
    ABRecordSetValue(recordRef,kABPersonLastNameProperty,(__bridge CFTypeRef)(lastName),NULL);
    //創(chuàng)建一個多值屬性厢绝,因為手機號可以有多個
    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);
}
3. 刪除聯(lián)系人
/* 刪除指定的記錄 */
- (void)removePersonWithRecord:(ABRecordRef)recordRef{
    ABAddressBookRemoveRecord(self.addressBook, recordRef, NULL);//刪除
    ABAddressBookSave(self.addressBook, NULL);//刪除之后提交更改
}
/* 根據(jù)姓名刪除記錄 */
- (void)removePersonWithName:(NSString *)personName{
    CFStringRef personNameRef = (__bridge CFStringRef)(personName);
    //根據(jù)人員姓名查找
    CFArrayRef recordsRef = ABAddressBookCopyPeopleWithName(self.addressBook, personNameRef);
    CFIndex count = CFArrayGetCount(recordsRef);//取得記錄數(shù)
    for (CFIndex i=0; i<count; ++i) {
        ABRecordRef recordRef = CFArrayGetValueAtIndex(recordsRef, i);//取得指定的記錄
        ABAddressBookRemoveRecord(self.addressBook, recordRef, NULL);//刪除
    }
    //刪除之后提交更改
    ABAddressBookSave(self.addressBook, NULL);
    CFRelease(recordsRef);
}
4. 修改聯(lián)系人
/**
 *  根據(jù)記錄ID修改聯(lián)系人信息
 *
 *  @param recordID   記錄唯一ID
 *  @param firstName  姓
 *  @param lastName   名
 *  @param homeNumber 工作電話
 */
- (void)modifyPersonWithRecordID:(ABRecordID)recordID
                       firstName:(NSString *)firstName
                        lastName:(NSString *)lastName
                      workNumber:(NSString *)workNumber
{
    //根據(jù)記錄ID獲取一條記錄
    ABRecordRef recordRef = ABAddressBookGetPersonWithRecordID(self.addressBook, recordID);
    //添加名
    ABRecordSetValue(recordRef,kABPersonFirstNameProperty,(__bridge CFTypeRef)(firstName),NULL);
    //添加姓
    ABRecordSetValue(recordRef,kABPersonLastNameProperty,(__bridge CFTypeRef)(lastName),NULL);
    //創(chuàng)建一個多值屬性昔汉,因為手機號可以有多個
    ABMutableMultiValueRef multiValueRef = ABMultiValueCreateMutable(kABStringPropertyType);
    //向多值屬性中添加工作電話
    ABMultiValueAddValueAndLabel(multiValueRef,(__bridge CFStringRef)(workNumber),kABWorkLabel,NULL);
    //添加屬性到指定記錄,這里添加的是多值屬性
    ABRecordSetValue(recordRef, kABPersonPhoneProperty, multiValueRef, NULL);
    //保存記錄拴清,提交更改
    ABAddressBookSave(self.addressBook, NULL);
    //釋放資源
    CFRelease(multiValueRef);
}
5. UITableView顯示
#pragma mark - TableView代理和數(shù)據(jù)源
- (NSInteger)tableView:(UITableView *)tableView
 numberOfRowsInSection:(NSInteger)section
{
    if (!self.allPerson) {
        return 0;
    }
    return self.allPerson.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *key = @"cellIdentify";
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:key];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
                                      reuseIdentifier:key];
    }
    //取得一條人員記錄
    ABRecordRef recordRef = (__bridge ABRecordRef)self.allPerson[indexPath.row];
    //取得記錄中得信息靶病,注意這里進行了強轉(zhuǎn),不用自己釋放資源
    NSString *firstName = (__bridge NSString *)ABRecordCopyValue(recordRef, kABPersonFirstNameProperty);
    NSString *lastName = (__bridge NSString *)ABRecordCopyValue(recordRef, kABPersonLastNameProperty);
    //獲取手機號口予,注意手機號是ABMultiValueRef類娄周,有可能有多條
    ABMultiValueRef phoneNumbersRef = ABRecordCopyValue(recordRef, kABPersonPhoneProperty);
    long 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));
    }
    //使用cell的tag存儲記錄ID
    cell.tag = ABRecordGetRecordID(recordRef);
    //記錄最后一個記錄的ID
    if (indexPath.row == self.allPerson.count - 1) {
        self.lastID = ABRecordGetRecordID(recordRef);
    }
    return cell;
}

6. UI點擊以及視圖控制器初始化和銷毀
- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    //請求訪問通訊錄并獲取通訊錄所有記錄
    [self requestAddressBook];
}
//由于在整個視圖控制器周期內(nèi)addressBook都駐留在內(nèi)存中,所以當控制器視圖銷毀時銷毀該對象
- (void)dealloc{
    if (self.addressBook != NULL) {
        CFRelease(self.addressBook);
    }
}
#pragma mark - UI點擊
- (IBAction)addPerson:(id)sender {
    //添加聯(lián)系人
    [self addPersonWithFirstName:@"liu"
                        lastName:@"ting"
                      workNumber:@"13412321332"];
    //獲取所有通訊錄記錄
    [self initAllPerson];
    //刷新表格
    [self.tableView reloadData];
}
- (IBAction)removePerson:(id)sender {
    //刪除聯(lián)系人
    [self removePersonWithName:@"liu ting"];
    //獲取所有通訊錄記錄
    [self initAllPerson];
    //刷新表格
    [self.tableView reloadData];
}
- (IBAction)changePerson:(id)sender {
    [self modifyPersonWithRecordID:self.lastID
                         firstName:@"XXXX"
                          lastName:@"YYY"
                        workNumber:@"1111111111"];
    //獲取所有通訊錄記錄
    [self initAllPerson];
    //刷新表格
    [self.tableView reloadData];
}

三沪停、AddressBookUI

AddressBookUI這個框架就提供了現(xiàn)成的控制器視圖供開發(fā)者使用煤辨,高度封裝化。

下面是這個框架中提供的控制器視圖:
  1. ABPersonViewController
    用于查看聯(lián)系人信息(可設置編輯)木张。
    需要設置displayedPerson屬性來設置要顯示或編輯的聯(lián)系人众辨。
  1. ABNewPersonViewController
    用于新增聯(lián)系人信息。
  2. ABUnknownPersonViewController
    用于顯示一個未知聯(lián)系人(尚未保存的聯(lián)系人)信息舷礼。
    需要設置displayedPerson屬性來設置要顯示的未知聯(lián)系人鹃彻。
  3. ABPeoplePickerNavigationController
    用于選擇聯(lián)系人。

前面三個控制器視圖均繼承于UIViewController妻献,在使用過程中必須使用一個UINavigationController進行包裝蛛株,否則只能看到視圖內(nèi)容無法進行操作团赁,并且必須處理控制器的關閉操作,可以通過代理方法獲得新增谨履、修改的聯(lián)系人欢摄。
最后一個控制器視圖繼承于UINavigationController,視圖自身的“組”屉符、“取消”按鈕操作不需要開發(fā)者來完成剧浸,例如開發(fā)者不用在點擊取消時關閉當前控制器視圖锹引,它自身已經(jīng)實現(xiàn)了關閉方法矗钟。

下面是這四個控制器的代理方法:
#pragma mark - ABPersonViewController代理方法
//選擇一個人員屬性后觸發(fā),返回值YES表示觸發(fā)默認行為操作嫌变,否則執(zhí)行代理中自定義的操作
- (BOOL)personViewController:(ABPersonViewController *)personViewController
        shouldPerformDefaultActionForPerson:(ABRecordRef)person
                    property:(ABPropertyID)property
                  identifier:(ABMultiValueIdentifier)identifier;
#pragma mark - ABNewPersonViewController代理方法
/* 
    完成新增(點擊取消和完成按鈕時調(diào)用),注意這里不用做實際的通訊錄增加工作吨艇,
    此代理方法調(diào)用時已經(jīng)完成新增,當保存成功的時候參數(shù)中得person會返回保存的記錄腾啥,如果點擊取消person為NULL
 */
- (void)newPersonViewController:(ABNewPersonViewController *)newPersonView
       didCompleteWithNewPerson:(ABRecordRef)person;
#pragma mark - ABUnknownPersonViewController代理方法
//保存未知聯(lián)系人時觸發(fā)
- (void)unknownPersonViewController:(ABUnknownPersonViewController *)unknownCardViewController
                 didResolveToPerson:(ABRecordRef)person;
#pragma mark - ABPeoplePickerNavigationController代理方法
//選擇一個聯(lián)系人后調(diào)用东涡,注意這個代理方法實現(xiàn)后選擇屬性的方法將不會再調(diào)用
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
                         didSelectPerson:(ABRecordRef)person;
//選擇屬性之后調(diào)用,注意如果上面的代理方法實現(xiàn)后此方法不會被調(diào)用
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker 
                         didSelectPerson:(ABRecordRef)person 
                                property:(ABPropertyID)property 
                              identifier:(ABMultiValueIdentifier)identifier;
//點擊取消按鈕調(diào)用
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker;
下面是具體代碼示例【我包裝了一個全局導航控制器】:
#import "addressBookUIViewController.h"
#import <AddressBookUI/AddressBookUI.h>

@interface addressBookUIViewController ()  <ABNewPersonViewControllerDelegate,
                                            ABUnknownPersonViewControllerDelegate,
                                            ABPeoplePickerNavigationControllerDelegate,
                                            ABPersonViewControllerDelegate>

@end

@implementation addressBookUIViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

#pragma mark - UI事件
//點擊添加聯(lián)系人
- (IBAction)addPersonClick:(UIButton *)sender {
    //創(chuàng)建添加聯(lián)系人視圖控制器
    ABNewPersonViewController *newPersonController = 
                  [[ABNewPersonViewController alloc] init];
    //設置代理
    newPersonController.newPersonViewDelegate = self;
    //注意必須有一層導航控制器才能使用倘待,否則不會出現(xiàn)取消和完成按鈕疮跑,無法進行保存等操作
    [self.navigationController pushViewController:newPersonController animated:YES];
}
//點擊未知聯(lián)系人
- (IBAction)unknownPersonClick:(UIButton *)sender {
    //創(chuàng)建未知聯(lián)系人視圖控制器
    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;//是否允許將聯(lián)系人添加到地址簿
    //釋放資源
    CFRelease(multiValueRef);
    CFRelease(recordRef);
    
    [self.navigationController pushViewController:unknownPersonController animated:YES];
}
//點擊顯示聯(lián)系人
- (IBAction)showPersonClick:(UIButton *)sender {
    //創(chuàng)建顯示聯(lián)系人視圖控制器
    ABPersonViewController *personController = [[ABPersonViewController alloc] init];
    //設置聯(lián)系人,取得id為1的聯(lián)系人記錄
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
    ABRecordRef recordRef = ABAddressBookGetPersonWithRecordID(addressBook, 1);
    personController.displayedPerson = recordRef;
    //設置代理
    personController.personViewDelegate = self;
    //設置其他屬性
    personController.allowsActions = YES;//是否顯示發(fā)送信息凸舵、共享聯(lián)系人等按鈕
    personController.allowsEditing = YES;//允許編輯
    
    [self.navigationController pushViewController:personController animated:YES];
}
//點擊選擇聯(lián)系人
- (IBAction)selectPersonClick:(UIButton *)sender {
    //創(chuàng)建選擇聯(lián)系人導航視圖控制器
    ABPeoplePickerNavigationController *peoplePickerController =
                [[ABPeoplePickerNavigationController alloc] init];
    //設置代理
    peoplePickerController.peoplePickerDelegate = self;
    //以模態(tài)彈出
    [self presentViewController:peoplePickerController animated:YES completion:nil];
}

#pragma mark - ABNewPersonViewController代理方法
/* 
    完成新增(點擊取消和完成按鈕時調(diào)用),注意這里不用做實際的通訊錄增加工作祖娘,
    此代理方法調(diào)用時已經(jīng)完成新增,當保存成功的時候參數(shù)中得person會返回保存的記錄啊奄,
    如果點擊取消person為NULL
 */
- (void)newPersonViewController:(ABNewPersonViewController *)newPersonView
       didCompleteWithNewPerson:(ABRecordRef)person
{
    //如果有聯(lián)系人信息
    if (person) {
        NSLog(@"%@ 信息保存成功.",(__bridge NSString *)(ABRecordCopyCompositeName(person)));
    }else{
        NSLog(@"點擊了取消.");
    }
    //返回主視圖窗口
    [self.navigationController popToRootViewControllerAnimated:YES];
    
}
#pragma mark - ABUnknownPersonViewController代理方法
//保存未知聯(lián)系人時觸發(fā)
- (void)unknownPersonViewController:(ABUnknownPersonViewController *)unknownCardViewController
                 didResolveToPerson:(ABRecordRef)person
{
    if (person) {
        NSLog(@"%@ 信息保存成功渐苏!",(__bridge NSString *)(ABRecordCopyCompositeName(person)));
    }
    //返回主視圖窗口
    [self.navigationController popToRootViewControllerAnimated:YES];
}

#pragma mark - ABPersonViewController代理方法
//選擇一個人員屬性后觸發(fā),返回值YES表示觸發(fā)默認行為操作菇夸,否則執(zhí)行代理中自定義的操作
- (BOOL)personViewController:(ABPersonViewController *)personViewController
        shouldPerformDefaultActionForPerson:(ABRecordRef)person
                    property:(ABPropertyID)property
                  identifier:(ABMultiValueIdentifier)identifier
{
    if (person) {
        NSLog(@"選擇了屬性:%d",property);
        NSLog(@"值為:%@", (__bridge NSString *)ABRecordCopyValue(person, property));
    }
    return NO;
}
#pragma mark - ABPeoplePickerNavigationController代理方法
//選擇一個聯(lián)系人后調(diào)用琼富,注意這個代理方法實現(xiàn)后選擇屬性的方法將不會再調(diào)用
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
                         didSelectPerson:(ABRecordRef)person
{
    if (person) {
        NSLog(@"選擇了%@.",(__bridge NSString *)(ABRecordCopyCompositeName(person)));
    }
}
//點擊取消按鈕后調(diào)用
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker{
    NSLog(@"取消選擇.");
}
@end



代碼Demo點這里:LearnDemo里面的AddressBookDemo

如果有什么問題可以在下方評論區(qū)留言,我會積極響應的庄新!O(∩_∩)O哈鞠眉!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市择诈,隨后出現(xiàn)的幾起案子械蹋,更是在濱河造成了極大的恐慌,老刑警劉巖吭从,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件朝蜘,死亡現(xiàn)場離奇詭異,居然都是意外死亡涩金,警方通過查閱死者的電腦和手機谱醇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門暇仲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人副渴,你說我怎么就攤上這事奈附。” “怎么了煮剧?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵斥滤,是天一觀的道長。 經(jīng)常有香客問我勉盅,道長佑颇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任草娜,我火速辦了婚禮挑胸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宰闰。我一直安慰自己茬贵,他們只是感情好,可當我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布移袍。 她就那樣靜靜地躺著解藻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪葡盗。 梳的紋絲不亂的頭發(fā)上螟左,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天,我揣著相機與錄音戳粒,去河邊找鬼路狮。 笑死,一個胖子當著我的面吹牛蔚约,可吹牛的內(nèi)容都是我干的奄妨。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼苹祟,長吁一口氣:“原來是場噩夢啊……” “哼砸抛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起树枫,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤直焙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后砂轻,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奔誓,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年搔涝,在試婚紗的時候發(fā)現(xiàn)自己被綠了厨喂。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片和措。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蜕煌,靈堂內(nèi)的尸體忽然破棺而出派阱,到底是詐尸還是另有隱情,我是刑警寧澤斜纪,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布贫母,位于F島的核電站,受9級特大地震影響盒刚,放射性物質(zhì)發(fā)生泄漏腺劣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一伪冰、第九天 我趴在偏房一處隱蔽的房頂上張望誓酒。 院中可真熱鬧,春花似錦贮聂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至靡狞,卻和暖如春耻警,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背甸怕。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工甘穿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人梢杭。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓温兼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親武契。 傳聞我的和親對象是個殘疾皇子募判,可洞房花燭夜當晚...
    茶點故事閱讀 45,851評論 2 361

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

  • 6轉(zhuǎn)載-->>IOS框架和服務 在iOS中框架是一個目錄,包含了共享資源庫咒唆,用于訪問該資源庫中儲存的代碼的頭文件届垫,...
    李小六_閱讀 3,620評論 2 24
  • 在iOS中框架是一個目錄,包含了共享資源庫全释,用于訪問該資源庫中儲存的代碼的頭文件装处,以及圖像、聲音文件等其他資源浸船。共...
    ch123閱讀 1,780評論 0 1
  • 文/半顆橙子@半間書房 臺灣女作家陳雪在深圳新書見面會上給書房君的簽名贈字妄迁,好喜歡她寫的這句話:“所有經(jīng)歷都不會白...
    半間書房閱讀 1,471評論 1 7
  • 這一段寫了學習的方法和有關知識的故事判族,人生有無數(shù)選擇躺盛,而這本書,不是答案形帮,但能幫助我們找到答案槽惫。
    文魁大腦俱樂部潘若琨閱讀 183評論 0 0
  • 很多時候我就希望下班回家之后有一碗速成的熱騰騰的面條,今天來介紹一個私人秘籍辩撑。 在周六日空余時間制作牛肉湯頭界斜,...
    追尋七色花閱讀 229評論 0 0