浅谈——iSO9前后通信录API的使用变迁史

iOS9之前
  • 1.AddressBookUI
    • 创建选择联系⼈人的控制器
    • 设置代理:选中联系⼈人的代理⽅方法(ABRecordRef person)/选中联系⼈人的某⼀一个属性
    • 弹出控制器
- (void)touchesBegan:(NSSet<UITouch *> *)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__);
}

  • 2.AddressBook
    • 判断授权状态
    • 如果是未决定,则请求授权 如果是已经授权,则获取联系⼈人信息
    • 创建通信录对象(ABAddressBook)
    • 拷⻉贝出来所有的联系⼈人(copyAllPeople(AddressBook))
    • 遍历所有的联系⼈人(每⼀一个联系⼈人都是ABRecordRef对象)
    • 获取联系⼈人的姓名和电话号码

  • 授权的判断

#import <AddressBook/AddressBook.h>

// ...
- (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<UITouch *> *)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);
        }
    }
}

  • 3.RHAddressBook
    • 去Github上,下载RHAddressBook
    • 查看该框架的引⽤用⽅方式
    • 使⽤用RHAddressBook框架
#import <AddressBook/AddressBook.h>
#import <RHAddressBook/AddressBook.h>

@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<UITouch *> *)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);
        }
    }
}


  • 4.桥接
    • __bridge type:需要释放对象
    • __bridge_transfer type:不需要释放对象
iOS9之后的API
  • 1.ContactsUI
    • 创建联系⼈人选择控制器
    • 设置代理:在代理⽅方法中拿到CNContact对象
    • 弹出控制器
#import <ContactsUI/ContactsUI.h>
// ...

- (void)touchesBegan:(NSSet<UITouch *> *)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__);
}

  • 2.Contacts
    • 获取授权状态
    • 如果是未决定,请求授权
    • 如果是已经授权,获取联系⼈人数据
    • 创建CNContactStore对象 CNContactFetchRequest : keys—>CNContact + 获取所有的联系⼈人:enum—>block->CNContact
  • 请求授权

#import <Contacts/Contacts.h>
// ...

- (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<UITouch *> *)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);
        }
    }];
}

  • 3.泛型
    • 集合中的泛型NSArray array : 该数组中只能放字符串  + 对象中某⼀一个属性限制: Person person : animal属性只能是Dog
 范例:
    (1)NSMutableArra<NSString *> *strings = […];

    (2NSMutableDictionary<NSString *, NSArray *> *dict = [...];

    (3)对象创建时的限制:Person<AnimalType : Animal*>对AnimalType的真实类型进行限制。案例如下:

#import <Foundation/Foundation.h>

@class Animal;

@interface Person<AnimalType : Animal*> : NSObject

/** 动物 */

@property (nonatomic, strong) AnimalType animalType;

@end

// 2.泛型对对象中的属性进行类型限制

    Person<Cat *> *person = [Person new];

    person.animalType = [[Cat alloc] init];



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值