- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1.创建一个选择联系人的控制器
ABPeoplePickerNavigationController *ppnc = [[ABPeoplePickerNavigationController alloc] init];
// 2.设置代理
ppnc.peoplePickerDelegate = self;
// 3.弹出控制器
[self presentViewController:ppnc animated:YES completion:nil];
}
#pragma mark - 实现ABPeoplePickerNavigationController的代理方法
/**
* 当用户选择某一个联系人的时候会执行该方法(如果实现了该方法,那么一定不会执行下面的代理方法)
*
* @param person 选中的联系人
*/
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person
{
// 1.获取用户的姓名
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSLog(@"%@ %@", lastName, firstName);
// 2.获取电话号码
// 2.1.获取所有的电话
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
// 2.2.将电话进行遍历
CFIndex phoneCount = ABMultiValueGetCount(phones);
for (int i = 0; i < phoneCount; i++) {
// 3.获取电话
NSString *phoneLabel = (__bridge_transfer NSString *)ABMultiValueCopyLabelAtIndex(phones, i);
NSString *phoneValue = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, i);
NSLog(@"%@ %@", phoneLabel, phoneValue);
}
}
/**
* 当用户选择某一个联系人的某一个属性的时候会执行该方法
*
* @param person 选中的联系人
* @param property 选中的联系人的属性
* @param identifier 每一个属性都有一个对应的表示
*/
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
NSLog(@"%s", __func__);
}
/**
* 当点击取消按钮时,会执行该方法
*
*/
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
NSLog(@"%s", __func__);
}
授权的判断
#import
// ...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 1.获取授权状态
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
// 2.判断授权状态
if (status == kABAuthorizationStatusNotDetermined) {
// 3.请求授权
// 3.1.创建通信录对象
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
// 3.2.请求授权
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { // 当用户决定是否授权的时候会执行该block
if (granted) { // 授权成功
NSLog(@"可以访问通信录");
} else { // 授权失败
NSLog(@"不可以访问通信录");
}
});
// 3.3.释放不再使用的对象
CFRelease(addressBook);
}
return YES;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1.判断授权状态
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
if (status != kABAuthorizationStatusAuthorized) return;
// 2.获取联系人
// 2.1.创建通信录对象
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
// 2.2.获取所有的联系人
CFArrayRef peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook);
// 2.3.遍历所有的联系人
CFIndex peopleCount = CFArrayGetCount(peopleArray);
for (int i = 0; i < peopleCount; i++) {
// 3.获取一条记录
ABRecordRef person = CFArrayGetValueAtIndex(peopleArray, i);
// 3.1.获取联系人的姓名
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
NSLog(@"%@ %@", firstName, lastName);
// 3.2.获取电话号码
// 3.2.1.获取所有的电话
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
// 3.3.2.遍历所有的电话号码
CFIndex phoneCount = ABMultiValueGetCount(phones);
for (int i = 0; i < phoneCount; i++) {
NSString *phoneLabel = (__bridge_transfer NSString *)ABMultiValueCopyLabelAtIndex(phones, i);
NSString *phoneValue = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, i);
NSLog(@"%@ %@", phoneLabel, phoneValue);
}
}
}
#import
#import
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 1.获取授权状态
RHAuthorizationStatus status = [RHAddressBook authorizationStatus];
// 2.判断授权状态
if (status == RHAuthorizationStatusNotDetermined) {
// 3.请求授权
// 3.1.创建通信录对象
RHAddressBook *addressBook = [[RHAddressBook alloc] init];
// 3.2.请求授权
[addressBook requestAuthorizationWithCompletion:^(bool granted, NSError *error) {
if (granted) {
NSLog(@"授权成功");
} else {
NSLog(@"授权失败");
}
}];
}
return YES;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1.获取授权状态
RHAuthorizationStatus status = [RHAddressBook authorizationStatus];
// 2.如果是已经授权,才能获取联系人
if (status != RHAuthorizationStatusAuthorized) return;
// 3.创建通信录对象
RHAddressBook *addressBook = [[RHAddressBook alloc] init];
// 4.获取所有的联系人
NSArray *peopleArray = addressBook.people;
// 5.遍历所有的记录
for (RHPerson *person in peopleArray) {
// 5.1.获取用户的姓名
NSString *firstname = person.firstName;
NSString *lastname = person.lastName;
NSLog(@"%@ %@", firstname, lastname);
// 5.2.获取电话号码
RHMultiValue *phones = person.phoneNumbers;
// 5.3.遍历所有的电话号码
for (int i = 0; i < phones.count; i++) {
NSString *phoneLabel = [phones labelAtIndex:i];
NSString *phoneValue = [phones valueAtIndex:i];
NSLog(@"%@ %@", phoneLabel, phoneValue);
}
}
}
#import
// ...
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1.创建选择联系人的界面
CNContactPickerViewController *cpvc = [[CNContactPickerViewController alloc] init];
// 2.设置代理
cpvc.delegate = self;
// 3.弹出控制器
[self presentViewController:cpvc animated:YES completion:nil];
}
#pragma mark - 实现CNContactPickerViewController的代理方法
/**
* 当用户选中某一个联系人的时候会执行该方法
*
* @param contact 选中的联系人
*/
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact
{
// 1.获取联系人的姓名
NSString *lastname = contact.familyName;
NSString *firstname = contact.givenName;
NSLog(@"%@ %@", lastname, firstname);
// 2.获取电话号码
for (CNLabeledValue *labelValue in contact.phoneNumbers) {
// 3.获取电话的label/value
NSString *phoneLabel = labelValue.label;
CNPhoneNumber *phoneNumber = labelValue.value;
NSString *phoneValue = phoneNumber.stringValue;
NSLog(@"%@ %@", phoneLabel, phoneValue);
}
}
/**
* 当用户选中某一个联系人的某一个属性时候会执行该方法
*
* @param contactProperty 选中的属性
*/
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty
{
NSLog(@"%s", __func__);
}
请求授权
#import
// ...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 1.获取授权状态
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
// 2.判断授权状态,如果是未决定请求授权
if (status == CNAuthorizationStatusNotDetermined) {
// 3.请求授权
// 3.1.创建CNContactStore对象
CNContactStore *store = [[CNContactStore alloc] init];
// 3.2.请求授权
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (error) {
NSLog(@"%@", error);
return;
}
if (granted) {
NSLog(@"授权成功");
} else {
NSLog(@"授权失败");
}
}];
}
return YES;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1.判断授权状态
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if (status != CNAuthorizationStatusAuthorized) return;
// 2.创建通信录对象
CNContactStore *store = [[CNContactStore alloc] init];
// 3.请求所有的联系人
// 3.1.创建联系人请求对象,并且传入keys:你准备获取的信息(姓familyName名givenName 电话号码:phones)
NSArray *keys = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
// 3.2.请求所有的联系人
NSError *error = nil;
[store enumerateContactsWithFetchRequest:request error:&error usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) { // 当遍历到一条记录就会执行该block
// 4.获取联系人
// 4.1.获取姓名
NSString *firstName = contact.givenName;
NSString *lastName = contact.familyName;
NSLog(@"%@ %@", firstName, lastName);
// 4.2.获取电话号码
NSArray *phones = contact.phoneNumbers;
for (CNLabeledValue *labelValue in phones) {
NSString *phoneLabel = labelValue.label;
CNPhoneNumber *phoneNumber = labelValue.value;
NSString *phoneValue = phoneNumber.stringValue;
NSLog(@"%@ %@", phoneLabel, phoneValue);
}
}];
}
范例:
(1)NSMutableArra<NSString *> *strings = […];
(2)NSMutableDictionary<NSString *, NSArray *> *dict = [...];
(3)对象创建时的限制:Person对AnimalType的真实类型进行限制。案例如下:
#import
@class Animal;
@interface Person
/** 动物 */
@property (nonatomic, strong) AnimalType animalType;
@end
// 2.泛型对对象中的属性进行类型限制
Person<Cat *> *person = [Person new];
person.animalType = [[Cat alloc] init];