iOS通讯录

作者: Kevin_wzx | 来源:发表于2017-05-03 12:17 被阅读203次

    1.简介

    1321491-fee8f9408163e66f.jpg
    1.1通讯录使用场景:

    1.电商类的 App,设置收货人电话号码。
    2.即时通讯类 App,添加手机联系人好友。

    1.2通讯录获取方案:
    屏幕快照 2017-05-15 下午1.59.14.png 987457-0e3476d43388a95e.png 1385290-c50d296d4e391d25.png
    1.3授权相关

    (1)从iOS6开始,必须得到用户授权访问通讯录才能在AppStore上架(即使不授权也有时候可以访问通讯录)
    (2)申请通讯录访问授权的代码,通常放在AppDelegate中~!
    (3)获得通讯录的授权状态函数:ABAddressBookGetAuthorizationStatus()

    例子:获取授权状态

    ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
    

    (4)用户授权状态有4种:

    kABAuthorizationStatusNotDetermined  用户未选择,用户还没有决定是否授权你的程序进行访问
    kABAuthorizationStatusRestricted iOS设备上一些许可配置阻止程序与通讯录数据库进行交互
    kABAuthorizationStatusDenied  用户明确的拒绝了你的程序对通讯录的访问
    kABAuthorizationStatusAuthorized  用户已经授权给你的程序对通讯录进行访问
    

    例子:在 AppDelegate的 didFinishLaunchingWithOptions方法中进行授权

    #import <AddressBook/AddressBook.h>
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        //1. 获取授权状态
        ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
        //2. 创建 AddrssBook
        ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
        //3. 没有授权时就授权
        if (status == kABAuthorizationStatusNotDetermined) {
            ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
                //3.1 判断是否出错
                if (error) {
                    return;
                }
                //3.2 判断是否授权
                if (granted) {
                    NSLog(@"已经授权");
                    CFRelease(addressBook);
                } else {
                    NSLog(@"没有授权");
                }
            });
        }
        CFRelease(addressBook);
        return YES;
    }
    

    2.通讯录的使用

    987457-a99ced4897708c01.png
    2.1 iOS9之前-->AddressBookUI的使用

    1.导入头文件,遵守协议

    #import "ViewController.h"
    #import <AddressBookUI/AddressBookUI.h>
    
    @interface ViewController () <ABPeoplePickerNavigationControllerDelegate>
    @end
    

    2.创建选择联系人的控制器

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        // 1.创建选择联系人的控制器
        ABPeoplePickerNavigationController *ppnc = [[ABPeoplePickerNavigationController alloc] init];
    
        // 2.设置代理
        ppnc.peoplePickerDelegate = self;
    
        // 3.弹出控制器
        if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
    {
       ABAddressBookRef bookRef = ABAddressBookCreate();
       ABAddressBookRequestAccessWithCompletion(bookRef, ^(bool granted, CFErrorRef error) {
           if (granted)
           {
               NSLog(@"授权成功!");
               [self presentViewController:pvc animated:YES completion:nil];
           }
           else
           {
               NSLog(@"授权失败!");
           }
       });
    }
    else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized)
    {
       [self presentViewController:pvc animated:YES completion:nil];
    }
    }
    

    3.实现代理方法

    #pragma mark - <ABPeoplePickerNavigationControllerDelegate>
    // 当用户选中某一个联系人时会执行该方法,并且选中联系人后会直接退出控制器
    - (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person
    {
        // 1.获取选中联系人的姓名
        CFStringRef lastName = ABRecordCopyValue(person, kABPersonLastNameProperty);
        CFStringRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
    
        // (__bridge NSString *) : 将对象交给Foundation框架的引用来使用,但是内存不交给它来管理
        // (__bridge_transfer NSString *) : 将对象所有权直接交给Foundation框架的应用,并且内存也交给它来管理
        NSString *lastname = (__bridge_transfer NSString *)(lastName);
        NSString *firstname = (__bridge_transfer NSString *)(firstName);
    
        NSLog(@"%@ %@", lastname, firstname);
    
        // 2.获取选中联系人的电话号码
        // 2.1.获取所有的电话号码
        ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
        CFIndex phoneCount = ABMultiValueGetCount(phones);
    
        // 2.2.遍历拿到每一个电话号码
        for (int i = 0; i < phoneCount; i++) {
            // 2.2.1.获取电话对应的key
            NSString *phoneLabel = (__bridge_transfer NSString *)ABMultiValueCopyLabelAtIndex(phones, i);
    
            // 2.2.2.获取电话号码
            NSString *phoneValue = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, i);
    
            NSLog(@"%@ %@", phoneLabel, phoneValue);
        }
    
       // 注意:管理内存 
        CFRelease(phones);
    }
    
    // 当用户选中某一个联系人的某一个属性时会执行该方法,并且选中属性后会退出控制器
    - (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
    {
        NSLog(@"%s", __func__);
    }
    

    小结:

    • Core Foundation 对象手动管理内存,如果是 Create、Copy、Retain 等字样创建的对象,需要手动 CFRelease。类似 Objective-C 的 MRC

      屏幕快照 2017-05-15 下午2.58.48.png
    • 在对应的代理方法中获取联系人信息

    // 1.选择联系人时使用(不展开详情)
    - (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person;
    
    // 2.选择联系人某个属性时调用(展开详情)
    - (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier;
    
    // 3.取消选中联系人时调用
    - (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker;
    
    注意:选择联系人的不展开详情(代理方法1)和展开详情(代理方法2)
    的代理方法都写了的时候,展开详情的代理方法就不执行
    
    2.2 iOS9之前-->AddressBook的使用
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        // 1.获取授权状态
        ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
    
        // 2.如果是已经授权,才能获取联系人(授权看简介中授权部分的内容)
        if (status != kABAuthorizationStatusAuthorized) return;
    
        // 3.创建通信录对象
        ABAddressBookRef addressBook = ABAddressBookCreate();
    
        // 4.获取所有的联系人
        CFArrayRef peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook);
        CFIndex peopleCount = CFArrayGetCount(peopleArray);
    
        // 5.遍历所有的联系人
        for (int i = 0; i < peopleCount; i++) {
            // 5.1.获取某一个联系人
            ABRecordRef person = CFArrayGetValueAtIndex(peopleArray, i);
            // 5.2.获取联系人的姓名
            NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
            NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
            NSLog(@"%@ %@", lastName, firstName);
    
            // 5.3.获取电话号码
            // 5.3.1.获取所有的电话号码
            ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
            CFIndex phoneCount = ABMultiValueGetCount(phones);
    
            // 5.3.2.遍历拿到每一个电话号码
            for (int i = 0; i < phoneCount; i++) {
                // 1.获取电话对应的key
                NSString *phoneLabel = (__bridge_transfer NSString *)ABMultiValueCopyLabelAtIndex(phones, i);
    
                // 2.获取电话号码
                NSString *phoneValue = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, i);
    
                NSLog(@"%@ %@", phoneLabel, phoneValue);
            }
    
            CFRelease(phones);
        }
    
      // 释放不再使用的对象
        CFRelease(addressBook);
        CFRelease(peopleArray);
    }
    

    补充:

    屏幕快照 2017-05-15 下午3.29.22.png
    2.3 iOS9之后-->ContactsUI的使用

    1.创建选择联系人的控制器

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        // 1.创建选择联系人的控制器
        CNContactPickerViewController *contactVc = [[CNContactPickerViewController alloc] init];
    
        // 2.设置代理
        contactVc.delegate = self;
    
        // 3.弹出控制器
        [self presentViewController:contactVc animated:YES completion:nil];
    }
    

    2.实现代理方法

    #pragma mark - <CNContactPickerDelegate>
    // 当选中某一个联系人时会执行该方法(不展开详情)
    - (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact
    {
        // 1.获取联系人的姓名
        NSString *lastname = contact.familyName;
        NSString *firstname = contact.givenName;
        NSLog(@"%@ %@", lastname, firstname);
    
        // 2.获取联系人的电话号码
        NSArray *phoneNums = contact.phoneNumbers;
        for (CNLabeledValue *labeledValue in phoneNums) {
            // 2.1.获取电话号码的KEY
            NSString *phoneLabel = labeledValue.label;
    
            // 2.2.获取电话号码
            CNPhoneNumber *phoneNumer = labeledValue.value;
            NSString *phoneValue = phoneNumer.stringValue;
    
            NSLog(@"%@ %@", phoneLabel, phoneValue);
        }
    }
    
    // 当选中某一个联系人的某一个属性时会执行该方法(展开详情)
    - (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty
    {
    }
    
    // 点击了取消按钮会执行该方法
    - (void)contactPickerDidCancel:(CNContactPickerViewController *)picker
    {  
    }
    
    注意:与 AddressBookUI 一样,选择联系人的不展开详情(代理方法1)和
    展开详情(代理方法2)的代理方法都写了的时候,展开详情的代理方法就不执行
    
    2.4 iOS9之后-->Contacts的使用
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        // 1.获取授权状态
        CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
    
        // 2.判断授权状态,如果不是已经授权,则直接返回
        if (status != CNAuthorizationStatusAuthorized) return;
    
        // 3.创建通信录对象
        CNContactStore *contactStore = [[CNContactStore alloc] init];
    
        // 4.创建获取通信录的请求对象
        // 4.1.拿到所有打算获取的属性对应的key
        NSArray *keys = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];
    
        // 4.2.创建CNContactFetchRequest对象
        CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
    
        // 5.遍历所有的联系人
        [contactStore enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
            // 1.获取联系人的姓名
            NSString *lastname = contact.familyName;
            NSString *firstname = contact.givenName;
            NSLog(@"%@ %@", lastname, firstname);
    
            // 2.获取联系人的电话号码
            NSArray *phoneNums = contact.phoneNumbers;
            for (CNLabeledValue *labeledValue in phoneNums) {
                // 2.1.获取电话号码的KEY
                NSString *phoneLabel = labeledValue.label;
    
                // 2.2.获取电话号码
                CNPhoneNumber *phoneNumer = labeledValue.value;
                NSString *phoneValue = phoneNumer.stringValue;
    
                NSLog(@"%@ %@", phoneLabel, phoneValue);
            }
        }];
    }
    

    其中4.1 描述的key-->访问的属性 Key,每个 Key 对应一个属性,iOS 9 新增,如果没有设置,访问该属性就会崩溃

    // 姓名前缀
    CNContactNamePrefixKey     
    // 名                 
    CNContactGivenNameKey                       
    // 中间名
    CNContactMiddleNameKey  
    // 姓                   
    CNContactFamilyNameKey            
    // 婚前姓         
    CNContactPreviousFamilyNameKey
    // 姓名后缀
    CNContactNameSuffixKey   
    // 昵称                   
    CNContactNicknameKey                        
    // 公司
    CNContactOrganizationNameKey                
    // 部门
    CNContactDepartmentNameKey                  
    // 职位
    CNContactJobTitleKey                        
    // 名字拼音或音标
    CNContactPhoneticGivenNameKey
    // 中间名拼音或音标              
    CNContactPhoneticMiddleNameKey
    // 姓拼音或音标
    CNContactPhoneticFamilyNameKey  
    // 公司拼音或音标            
    CNContactPhoneticOrganizationNameKey      
    // 生日  
    CNContactBirthdayKey   
    // 农历                    
    CNContactNonGregorianBirthdayKey    
    // 备注        
    CNContactNoteKey                            
    // 图片
    CNContactImageDataKey                       
    // 缩略图
    CNContactThumbnailImageDataKey              
    // 图片是否允许访问
    CNContactImageDataAvailableKey              
    // 类型
    CNContactTypeKey                            
    // 号码
    CNContactPhoneNumbersKey                    
    // 电子邮件
    CNContactEmailAddressesKey                  
    // 地址
    CNContactPostalAddressesKey                 
    // 日期
    CNContactDatesKey   
    // URL                        
    CNContactUrlAddressesKey                    
    // 关联人
    CNContactRelationsKey                       
    // 社交
    CNContactSocialProfilesKey                  
    // 即时通讯
    CNContactInstantMessageAddressesKey
    

    相关链接:iOS 通讯录开发的所有姿势http://www.jianshu.com/p/55d1c90f62c8#

    3.实例代码展示

    效果:点击通讯录,选择联系人,然后选择相应号码返回

    屏幕快照 2017-08-24 下午3.48.52.png 屏幕快照 2017-08-24 下午4.07.54.png 屏幕快照 2017-08-24 下午4.08.13.png

    代码如下:


    屏幕快照 2017-08-24 下午3.55.48.png

    代理为:ABPeoplePickerNavigationControllerDelegate,
    CNContactPickerDelegate

    屏幕快照 2017-08-24 下午3.54.00.png 屏幕快照 2017-08-24 下午3.57.27.png 屏幕快照 2017-08-24 下午3.58.39.png 屏幕快照 2017-08-24 下午3.59.56.png

    相关文章

      网友评论

      本文标题:iOS通讯录

      本文链接:https://www.haomeiwen.com/subject/riuktxtx.html