iOS通讯录(纯纯的干货)

一、iOS8.0

 

1、访问用户通讯录的两个框架

 

(1)AddressBookUI.framework

提供了联系人列表界面、联系人详情界面、添加联系人界面等,一般用于选择联系人

 

(2)AddressBook.framework

   <1>纯C语言的API,仅仅是获得联系人数据

   <2>没有提供UI界面展示,需要自己搭建联系人展示界面

   <3>里面的数据类型大部分基于Core Foundation框架,使用起来非常不方便

 

(3)从iOS6开始,需要得到用户的授权才能访问通讯录(没UI界面的),因此在使用之前,需要检查用户是否已经授权

获得通讯录的授权状态:ABAddressBookGetAuthorizationStatus()

 

 

2、使用AddressBookUI.framework示例

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

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //创建通讯录控制器
    //弹出控制器
    ABPeoplePickerNavigationController *picker  = [[ABPeoplePickerNavigationController alloc]init];
    
    //设置代理
    picker.peoplePickerDelegate = self;
    
    //展示通讯录界面
    [self presentViewController:picker animated:YES completion:nil];
    
}

//选中一个人的基本信息就会调用
//参数1:控制器  参数2:选择的person的信息
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person
{
    /*
    1、关于内存的管理:静态分析工具
    
    2、因为是C语言的API(CoreFoundation),所有使用了create、copy等获取的对象都需要释放 -> CFRelease
    
    3、桥接
    __bridge  默认桥接
    __bridge_transfer  桥接 coreF  -> ocF   转让对象的所有权(释放权)
    __bridge_retained  桥接 ocF  -> coreF   转让对象的所有权   
    */
    


    //返回的ABRecordRef是一条记录,包括了一个人的所有信息字段    
    //通过“函数”获得姓名
    CFStringRef strfirst =   ABRecordCopyValue(person, kABPersonFirstNameProperty);
    CFStringRef strlast =   ABRecordCopyValue(person, kABPersonLastNameProperty);
    
    //在桥接时,转让了对象的所有权,转给了OC来管理(自动释放了)
    NSString *strF = (__bridge_transfer NSString *)(strfirst);
    NSString *strL = (__bridge_transfer NSString *)(strlast);
    NSLog(@"%@  %@",strF,strL);

    //电话号码:ABMultiValueRef 封装一个保存了很多电话的一个类型,类似OC中的数组
    ABMultiValueRef  multiValues =   ABRecordCopyValue(person, kABPersonPhoneProperty);
    //获得这个集合的数量(电话号码的数量)
    CFIndex index = ABMultiValueGetCount(multiValues);
    //遍历集合,打印电话
    for (CFIndex i = 0; i < index; i++) {
      
        CFStringRef strPhone = ABMultiValueCopyValueAtIndex(multiValues, i);
        NSString *phoneStr = (__bridge_transfer  NSString *)(strPhone);
        NSLog(@"%@",phoneStr);
    }
    
    //释放内存前,先判断该字段存在
    if (multiValues != NULL) {
        CFRelease(multiValues);
    }
    
}

//选择中一个人信息的属性才会调用
//注意点:如果实现“选中个人信息的代理方法” 当前方法不执行,因为属性界面不会显示
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
        NSLog(@"property %zd",property);
}

//点击取消了 就会调用
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
    NSLog(@"peoplePickerNavigationControllerDidCancel");
}

 

3、使用AddressBook.framework框架示例

 

#import "ViewController.h"
#import <AddressBook/AddressBook.h>
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    //获取用户的授权:授权状态
    /*
     kABAuthorizationStatusNotDetermined = 0,    // deprecated, use CNAuthorizationStatusNotDetermined
     kABAuthorizationStatusRestricted,           // deprecated, use CNAuthorizationStatusRestricted
     kABAuthorizationStatusDenied,               // deprecated, use CNAuthorizationStatusDenied
     kABAuthorizationStatusAuthorized            // 已经授权
     */
    
    
    //通过函数获得授权状态
    ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
    
    if (status ==  kABAuthorizationStatusNotDetermined) {
        
        ABAddressBookRef book =  ABAddressBookCreateWithOptions(NULL, NULL);
        //申请授权
        //参数1 通讯录对象   参数2block 回调
        ABAddressBookRequestAccessWithCompletion(book, ^(bool granted, CFErrorRef error) {
            if (granted) {
                NSLog(@"授权成功!");
            }else{
                NSLog(@"授权失败!");
            }
        });
    }
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //获取联系人信息
    //获得姓名
    
    //通讯录是单例,在哪里获取都是一样的
    ABAddressBookRef book = ABAddressBookCreateWithOptions(NULL, NULL);
    
    //获取所有人的信息
    CFArrayRef allpeople =  ABAddressBookCopyArrayOfAllPeople(book);

    //数量
    CFIndex count =  CFArrayGetCount(allpeople);
    
    for (CFIndex i = 0; i <count ; i++) {
        
        //获得没一条记录
        ABRecordRef record =  CFArrayGetValueAtIndex(allpeople, i);
       
        //获得姓名
        CFStringRef strFirst =  ABRecordCopyValue(record, kABPersonFirstNameProperty);
        NSString *str =  (__bridge_transfer NSString *)strFirst;
        NSLog(@"%@",str);
       
        //获得电话号码
        ABMultiValueRef multivalue =  ABRecordCopyValue(record, kABPersonPhoneProperty);
        
        for (CFIndex i = 0; i < ABMultiValueGetCount(multivalue); i++) {
           CFStringRef phoneStr =   ABMultiValueCopyValueAtIndex(multivalue, i);
            NSString *phone = (__bridge_transfer  NSString *)(phoneStr);
            
            NSLog(@"%@",phone);
        }
        
        CFRelease(multivalue);

    }
    
    CFRelease(allpeople);
    CFRelease(book);
    
}
@end

 

 

 

 

二、iOS9.0

 

1、访问用户通讯录的两个框架

 (1)ContactsUI

   <1>AddressBookUI的升级,不需要授权

   <2>通过代理返回需要的数据

 (2)Contacts

  AddressBook.framework 的升级

 

2、ContactsUI示例

 

#import "ViewController.h"
#import <ContactsUI/ContactsUI.h>
@interface ViewController ()<CNContactPickerDelegate>

@end

@implementation ViewController

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //不需要授权
    //创建通讯录控制器
    CNContactPickerViewController *picker = [[CNContactPickerViewController alloc]init];
    //设置代理拿到数据本身
    picker.delegate = self;
    //展示通讯录
    [self presentViewController:picker animated:YES completion:nil];
}


//实现代理方法
//选择一个联系人的基本信息
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact;
{

    //重点注意contact的类型和属性
    
   NSArray *allArray = contact.phoneNumbers;
    for (CNLabeledValue * labeledValue in allArray) {
        CNPhoneNumber *num = labeledValue.value;
        NSLog(@"num = %@",num.stringValue);
        NSLog(@"===%@ ===%@",labeledValue.value,labeledValue.label);
    }
}
//选择一个联系人属性信息
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty;
{
    NSLog(@"didSelectContactProperty");
}

@end

 

 

3、Contacts示例

 

#import "ViewController.h"
#import <Contacts/Contacts.h>
@interface ViewController ()
@property (nonatomic, strong) CNContactStore *store;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //获取授权状态
    CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
    
    //如果没有授权过需要请求用户的授权
    CNContactStore *store = [[CNContactStore alloc]init];
    self.store = store;

    if (status == CNAuthorizationStatusNotDetermined) {
        //请求授权
        [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
           
            if (granted) {
                NSLog(@"授权成功!");
            }else{
                NSLog(@"授权失败!");
            }
            
        }];
    }
    
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //name  phone
    CNContactFetchRequest *request = [[CNContactFetchRequest alloc]initWithKeysToFetch:@[CNContactGivenNameKey,CNContactPhoneNumbersKey]];
    
    //参数1  封装查询请求
   [self.store enumerateContactsWithFetchRequest: request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
       //返回的数据 CNContact
       NSLog(@"%@",contact.givenName);
       
       NSLog(@"%@",contact.phoneNumbers);
       
       
   }];
}
@end

 

posted @ 2016-04-28 20:05  执着的怪味豆  阅读(370)  评论(0编辑  收藏  举报