iOS通讯录开发框架的学习和使用(一)

iOS9之前有两个通讯录相关的框架,AddressBookUI.framework 和 AddressBook.framework。前者包含UI界面,后者无UI界面(如微信电话本),可以自己搭建UI界面。后者是纯C语言的API,仅仅是获得联系人数据,里面的数据大部分是基于Core Foundation框架,使用起来异常麻烦。注意:需要授权才能访问通讯录。iOS9之后出现一个ContactsUI框架,这个框架相比前两者使用起来要方便很多。虽然如此,但是这个从这个框架的名字中可以看出是带有UI界面的,但是很多时候我们可能要自定义,所以除了这个框架,iOS9之前的框架也是很有必要学习的。
先看一下AddressBookUI框架。使用这个框架要导入头文件,并且要遵守这个协议。

//1.创建联系人选择控制器
    ABPeoplePickerNavigationController *picker = [ABPeoplePickerNavigationController new];
    //2.设置代理  注意不是delegate  
    picker.peoplePickerDelegate = self;
    //3.模态视图弹出
    [self presentViewController:picker animated:YES completion:nil];

下面的是对应的一个代理方法,当选中联系人的时候会调用该方法。

- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person{
    //需求:获取姓名和电话
    //1.获取姓和名
    //一个Record就相当于一条记录
    //姓
    CFStringRef lastName = ABRecordCopyValue(person, kABPersonLastNameProperty);
    NSString *lastNameStr = (__bridge NSString *)(lastName);//桥接
    NSLog(@"lastName=%@",lastNameStr);
    //名
    CFStringRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
    NSString *firstNameStr = (__bridge NSString *)(firstName);//桥接
    NSLog(@"firstName=%@",firstNameStr);
    //CF对象一定要释放
    CFRelease(lastName);
    CFRelease(firstName);
    
    //2.获取电话   注意可能有多个电话
    ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
    //2.1 获取电话个数  phones.count不可以获取个数
    CFIndex count = ABMultiValueGetCount(phones);
    //2.2 遍历联系人
    for (CFIndex i = 0 ; i < count; i++) {
        //2.3 获取联系电话的标签
        //两种写法
        NSString *label = (__bridge_transfer NSString *)ABMultiValueCopyLabelAtIndex(phones, i);
        //NSString *label = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(phones, i));
        NSLog(@"电话标签:%@",label);//_$!!$_
        
        //2.4 获取联系人电话
        NSString *value =(__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, i);
        NSLog(@"电话号码:%@",value);
    }
    //3.释放CF对象
    CFRelease(phones)
}

//选中某个联系人的某个属性时候调用
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{
    NSLog(@"%d",property);
}
//取消选中联系人调用
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker{
   
}

关于上面的三个代理方法要稍微说明一下。第一个代理方法,在iOS7下必须能实现此方法,否则会崩溃,在选中摸个联系人的时候会调用此方法。前两个代理方法,如果同时实现只会执行第一个方法。一般情况下只要求执行下面两个方法中的一个即可,如果实现第二个会进入联系人详情界面。

关于iOS7和iOS8的适配问题:
1.在iOS7下必须能实现以下第一个方法,否则会崩溃
2.iOS7可以同时实现两个代理方法,而iOS8只能实现一个(同时实现只会执行第一个方法)
3.iOS7选择联系人代理方法,如果返回YES则会跳到下一个界面,如果返回NO,必须手动实现取消控制器的方法。iOS8默认会在点击联系人的时候,自动取消显示控制器。
注意:如果想适配iOS7和iOS,代理方法必须都写,这样才可以适配7和8

上面涉及这么多和Core Foundation相关的东西,这里就稍微做一些额外的补充。
1. Core Foundation 和 Foundation桥接的问题,桥接有几种方法?
共三种方法,具体如下:
a、CFStringRef lastName = ABRecordCopyValue(person, kABPersonLastNameProperty);
NSString *lastNameStr = (__bridge NSString *)(lastName);
CFRelease(lastName);
b、以下两种写法形式,意思一样。
NSString *label = (__bridge_transfer NSString *)ABMultiValueCopyLabelAtIndex(phones, i);
NSString *label = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(phones, i));
c、
// (__bridge <#type#>)<#expression#>) 只是让Foundation框架暂时使用CF框架对象,一般都要释放CF对象
//(__bridge_transfer <#Objective-C type#>)<#expression#>) CF框架移交管理权给Foundation框架
//(__bridge_retained <#CF type#>)<#expression#>) 前面两个是将CF对象转为Foundation对象,而这个是将Foundation对象转为CF对象,一般不常用
2.注意事项:
CF对象一定要释放,否则出现内存泄露。CFRelease(lastName);

你可能感兴趣的:(iOS通讯录开发框架的学习和使用(一))