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示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#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框架示例

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#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示例

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#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示例

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#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 @   执着的怪味豆  阅读(381)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示