iOS实现封装一个获取通讯录的工具类详解

前言

本文给大家介绍了关于iOS如何封装一个获取通讯录工具类的相关内容,iOS获取通讯录一共有4个framework: AddressBook, AddressBookUI, Contacts, ContactsUI; 其中 AddressBook 和 AddressBookUI 已经被iOS9时 deprecated 了, 而推出了Contacts 和 ContactsUI 取代之. 其中 AddressBookUI 和 ContactsUI 是picker出一个界面提供选择一条联系人信息并且是不需要手动授权, AddressBook 和 Contacts 是获取全部通讯录数据并且需要手动授权.下面来一起看看详细的介绍吧。

注意:在iOS10获取通讯录权限需主动在info.plist里添加上提示信息. 不然会崩溃. 在info.plist里添加一对key和value

  • key: Privacy - Contacts Usage Description
  • value: 自由发挥, 这里随便写一句: 是否允许此App访问你的通讯录?

ContactsModel

新建两个数据模型文件来保存获取的通讯录数据

ContactsModel.h

#import <Foundation/Foundation.h>

@interface ContactsModel : NSObject
@property (nonatomic, copy) NSString *num;
@property (nonatomic, copy) NSString *name;

- (instancetype)initWithName:(NSString *)name num:(NSString *)num;
@end

ContactsModel.m

#import "ContactsModel.h"

@implementation ContactsModel

- (instancetype)initWithName:(NSString *)name num:(NSString *)num {
 if (self = [super init]) {
  self.name = name;
  self.num = num;
 }
 return self;
}

@end

ContactsHelp

这是获取通讯录的工具类.

ContactsHelp.h

#import <UIKit/UIKit.h>
#import "ContactsModel.h"

typedef void(^ContactBlock)(ContactsModel *contactsModel);

@interface ContactsHelp : NSObject

+ (NSMutableArray *)getAllPhoneInfo;

- (void)getOnePhoneInfoWithUI:(UIViewController *)target callBack:(ContactBlock)block;

@end

ContactsHelp.m

#import "ContactsHelp.h"
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
#import <Contacts/Contacts.h>
#import <ContactsUI/ContactsUI.h>

#define iOS9 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0)

@interface ContactsHelp () <CNContactPickerDelegate, ABPeoplePickerNavigationControllerDelegate>
@property(nonatomic, strong) ContactsModel *contactModel;
@property(nonatomic, strong) ContactBlock myBlock;
@end

@implementation ContactsHelp

+ (NSMutableArray *)getAllPhoneInfo {
 return iOS9 ? [self getContactsFromContacts] : [self getContactsFromAddressBook];
}

- (void)getOnePhoneInfoWithUI:(UIViewController *)target callBack:(void (^)(ContactsModel *))block {
 if (iOS9) {
  [self getContactsFromContactUI:target];
 } else {
  [self getContactsFromAddressBookUI:target];
 }
 self.myBlock = block;
}

#pragma mark - AddressBookUI
- (void)getContactsFromAddressBookUI:(UIViewController *)target {
 ABPeoplePickerNavigationController *pickerVC = [[ABPeoplePickerNavigationController alloc] init];
 pickerVC.peoplePickerDelegate = self;
 [target presentViewController:pickerVC animated:YES completion:nil];
}

- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person {
 ABMultiValueRef phonesRef = ABRecordCopyValue(person, kABPersonPhoneProperty);
 if (!phonesRef) { return; }
 NSString *phoneValue = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phonesRef, 0);

 CFStringRef lastNameRef = ABRecordCopyValue(person, kABPersonLastNameProperty);
 CFStringRef firstNameRef = ABRecordCopyValue(person, kABPersonFirstNameProperty);
 NSString *lastname = (__bridge_transfer NSString *)(lastNameRef);
 NSString *firstname = (__bridge_transfer NSString *)(firstNameRef);
 NSString *name = [NSString stringWithFormat:@"%@%@", lastname == NULL ? @"" : lastname, firstname == NULL ? @"" : firstname];
 NSLog(@"姓名: %@", name);

 ContactsModel *model = [[ContactsModel alloc] initWithName:name num:phoneValue];
 NSLog(@"电话号码: %@", phoneValue);

 CFRelease(phonesRef);
 if (self.myBlock) self.myBlock(model);
}

#pragma mark - ContactsUI
- (void)getContactsFromContactUI:(UIViewController *)target {
 CNContactPickerViewController *pickerVC = [[CNContactPickerViewController alloc] init];
 pickerVC.delegate = self;
 [target presentViewController:pickerVC animated:YES completion:nil];
}

- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact {
 NSString *name = [NSString stringWithFormat:@"%@%@", contact.familyName == NULL ? @"" : contact.familyName, contact.givenName == NULL ? @"" : contact.givenName];
 NSLog(@"姓名: %@", name);

 CNPhoneNumber *phoneNumber = [contact.phoneNumbers[0] value];
 ContactsModel *model = [[ContactsModel alloc] initWithName:name num:[NSString stringWithFormat:@"%@", phoneNumber.stringValue]];
 NSLog(@"电话号码: %@", phoneNumber.stringValue);

 if (self.myBlock) self.myBlock(model);
}

#pragma mark - AddressBook
+ (NSMutableArray *)getContactsFromAddressBook {
 ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
 CFErrorRef myError = NULL;
 ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &myError);
 if (myError) {
  [self showErrorAlert];
  if (addressBook) CFRelease(addressBook);
  return nil;
 }

 __block NSMutableArray *contactModels = [NSMutableArray array];
 if (status == kABAuthorizationStatusNotDetermined) { // 用户还没有决定是否授权你的程序进行访问
  ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
   if (granted) {
    contactModels = [self getAddressBookInfo:addressBook];
   } else {
    [self showErrorAlert];
    if (addressBook) CFRelease(addressBook);
   }
  });
  // 用户已拒绝 或 iOS设备上的家长控制或其它一些许可配置阻止程序与通讯录数据库进行交互
 } else if (status == kABAuthorizationStatusDenied || status == kABAuthorizationStatusRestricted) {
  [self showErrorAlert];
  if (addressBook) CFRelease(addressBook);
 } else if (status == kABAuthorizationStatusAuthorized) { // 用户已授权
  contactModels = [self getAddressBookInfo:addressBook];
 }
 return contactModels;
}

+ (NSMutableArray *)getAddressBookInfo:(ABAddressBookRef)addressBook {
 CFArrayRef peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook);
 NSInteger peopleCount = CFArrayGetCount(peopleArray);
 NSMutableArray *contactModels = [NSMutableArray array];

 for (int i = 0; i < peopleCount; i++) {
  ABRecordRef person = CFArrayGetValueAtIndex(peopleArray, i);
  ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
  if (phones) {
   NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
   NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
   NSString *name = [NSString stringWithFormat:@"%@%@", lastName == NULL ? @"" : lastName, firstName == NULL ? @"" : firstName];
   NSLog(@"姓名: %@", name);

   CFIndex phoneCount = ABMultiValueGetCount(phones);
   for (int j = 0; j < phoneCount; j++) {
    NSString *phoneValue = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, j);
    NSLog(@"电话号码: %@", phoneValue);
    ContactsModel *model = [[ContactsModel alloc] initWithName:name num:phoneValue];
    [contactModels addObject:model];
   }
  }
  CFRelease(phones);
 }

 if (addressBook) CFRelease(addressBook);
 if (peopleArray) CFRelease(peopleArray);

 return contactModels;
}

#pragma mark - Contacts
+ (NSMutableArray *)getContactsFromContacts {
 CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
 CNContactStore *store = [[CNContactStore alloc] init];
 __block NSMutableArray *contactModels = [NSMutableArray array];

 if (status == CNAuthorizationStatusNotDetermined) { // 用户还没有决定是否授权你的程序进行访问
  [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
   if (granted) {
    contactModels = [self getContactsInfo:store];
   } else {
    [self showErrorAlert];
   }
  }];
  // 用户已拒绝 或 iOS设备上的家长控制或其它一些许可配置阻止程序与通讯录数据库进行交互
 } else if (status == CNAuthorizationStatusDenied || status == CNAuthorizationStatusRestricted) {
  [self showErrorAlert];
 } else if (status == CNAuthorizationStatusAuthorized) { // 用户已授权
  contactModels = [self getContactsInfo:store];
 }

 return contactModels;
}

+ (NSMutableArray *)getContactsInfo:(CNContactStore *)store {
 NSArray *keys = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];
 CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
 NSMutableArray *contactModels = [NSMutableArray array];

 [store enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
  NSString *name = [NSString stringWithFormat:@"%@%@", contact.familyName == NULL ? @"" : contact.familyName, contact.givenName == NULL ? @"" : contact.givenName];
  NSLog(@"姓名: %@", name);

  for (CNLabeledValue *labeledValue in contact.phoneNumbers) {
   CNPhoneNumber *phoneNumber = labeledValue.value;
   NSLog(@"电话号码: %@", phoneNumber.stringValue);
   ContactsModel *model = [[ContactsModel alloc] initWithName:name num:phoneNumber.stringValue];
   [contactModels addObject:model];
  }
 }];

 return contactModels;
}

#pragma mark - Error
+ (void)showErrorAlert {
 NSLog(@"授权失败, 请允许app访问您的通讯录, 在手机的”设置-隐私-通讯录“选项中设置允许");
}

@end

使用

#import "ContactsHelp.h"
#import "ContactsModel.h"

...

@property(nonatomic, strong) ContactsHelp *contactsHelp;

...

- (IBAction)btn_getOne {
 self.contactsHelp = [[ContactsHelp alloc] init];
 [self.contactsHelp getOnePhoneInfoWithUI:self callBack:^(ContactsModel *contactModel) {
  NSLog(@"-----------");
  NSLog(@"%@", contactModel.name);
  NSLog(@"%@", contactModel.num);
 }];
}

- (IBAction)btn_getAll {
 NSMutableArray *contactModels = [ContactsHelp getAllPhoneInfo];
 [contactModels enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  ContactsModel *model = obj;
  NSLog(@"-----------");
  NSLog(@"%@", model.name);
  NSLog(@"%@", model.num);
 }];
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • 详解iOS获取通讯录的4种方式

    本文实例为大家分享了iOS获取通讯录的4种方式,供大家参考,具体内容如下 使用场景 一些App通过手机号码来推荐好友,如 微博.支付宝 首先客户端会获取通讯录中的所有手机号然后将这些手机号提交到App服务器中,服务器会查找每个手机号对应的App账号如QQ号码返回到客户端,然后客户端根据服务器返回的账号列表来推荐好友. 获取联系人方式 方案一:AddressBookUI.framework框架 提供了联系人列表界面.联系人详情界面.添加联系人界面等 一般用于选择联系人 方案二:AddressBoo

  • IOS 通讯录信息读取兼容的实现方法

    IOS 通讯录信息读取兼容的实现方法 项目中有一个功能需要读取通讯录中联系人的手机.在iOS8以前都是可用的,主要使用如下三个代理方法来实现 - (void) peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker - (BOOL) peoplePickerNavigationController:(ABPeoplePickerNavigationController

  • 如何自定义iOS通讯录

    苹果给用户提供了自己的通讯录,但是根据业务的需求,需要自定义通讯录,我们就需要根据业务需求来自定义. 首先我们需要知道苹果的提供的一些Foundation.UIKit框架,了解其中的一些特性,可以打开手机查看苹果系统提供的原生的通讯录,可以看到: 1.搜索框 2.右侧搜索条 3.联系人分组 4.添加联系人 5.获取联系人头像及联系方式 根据需求,可以总结出自定义通讯录需要做的一些功能,一项大的功能可以差分成一些小的功能,然后一个一个实现,将复杂的问题差分成小问题解决. 1.自定义搜索框 2.获取

  • iOS开发中使app获取本机通讯录的实现代码实例

    一.在工程中添加AddressBook.framework和AddressBookUI.framework 二.获取通讯录 1.在infterface中定义数组并在init方法中初始化 复制代码 代码如下: NSMutableArray *addressBookTemp;   - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {     addressBookTemp = [NSMut

  • iOS获取手机通讯录方式方法(最新)

    最近学习了iOS获取手机通讯录方式方法,现在分享给大家.希望此文章对各位有所帮助. 一.iOS 9 以前的通讯录框架 AddressBookUI框架:提供了联系人列表界面.联系人详情界面.添加联系人界面等,一般用于选择联系人. AddressBook 框架:纯 C 语言的 API,仅仅是获得联系人数据.没有提供 UI 界面展示,需要自己搭建联系人展示界面. 二. iOS 9 以后最新通讯录框架 ContactsUI 框架:拥有 AddressBookUI 框架的所有功能,使用起来更加的面向对象.

  • IOS中获取本地通讯录联系人以及汉字首字母排序

    iOS中获取手机通讯录中的联系人信息: /*** 加载本地联系人*/ - (void)loadLocalContacts { //新建一个通讯录类 ABAddressBookRef addressBooks = nil; if (DeviceVersion < 6.0) { addressBooks = ABAddressBookCreate(); } else { addressBooks = ABAddressBookCreateWithOptions(NULL, NULL); //获取通讯

  • IOS 通讯录的访问和修改的实现

    IOS 通讯录的访问和修改的实现 在iOS端可以通过AddressBook或者AddressBookUI两个框架实现,区别是第二个框架带视图,一般使用第一个框架就够了. 下面介绍AddressBook框架的使用,注意这个是C语言框架,使用起来比较麻烦. ①请求授权 先判断授权状态,如果未授权则进行授权. // 1.主动请求授权,先判断授权状态 NSInteger state = ABAddressBookGetAuthorizationStatus(); if (state == kABAuth

  • iOS实现封装一个获取通讯录的工具类详解

    前言 本文给大家介绍了关于iOS如何封装一个获取通讯录工具类的相关内容,iOS获取通讯录一共有4个framework: AddressBook, AddressBookUI, Contacts, ContactsUI; 其中 AddressBook 和 AddressBookUI 已经被iOS9时 deprecated 了, 而推出了Contacts 和 ContactsUI 取代之. 其中 AddressBookUI 和 ContactsUI 是picker出一个界面提供选择一条联系人信息并且

  • 使用纯JavaScript封装一个消息提示条功能示例详解

    目录 介绍 思路&布局 操作逻辑 完整代码 介绍 一个类似Element UI.Ant-Design UI等 UI 框架的消息提示功能,方便在任何网页环境中直接调用函数使用:区别在不依赖 js 及 css 引用,而是使用纯 js 进行封装实现,代码更精简,同时保持和 UI 框架一样的视觉效果(可自行修改成自己喜欢的样式) 代码仓库 在线预览效果(点击[登录].[点击复制]按钮时触发提示效果) 思路&布局 先来写单个提示条,并实现想要的过渡效果,最后再用逻辑操作输出节点即可:这里不需要父节点

  • Java项目常见工具类详解

    目录 JWT工具类 MD5工具类 视频点播工具类 公共常量工具类 日期操作工具类 Http客户端工具类 获取IP工具类 JWT工具类 这里一共涉及四个方法: 传入用户信息获得token 传入token字符串判断token是否存在与有效 传入HttpServletRequest,通过获取Header中的token判断是否存在与有效 根据token获取用户id public class JwtUtils { //token过期时间 public static final long EXPIRE =

  • 微信小程序 常用工具类详解及实例

    微信小程序 常用工具类详解 前言: 做微信小程序当中,会遇到好多的工具类util.js,这里记载下来以便平常使用 (Ps:建议通过目录查看) -获取日期(格式化) function formatTime(date) { var year = date.getFullYear() var month = date.getMonth() + 1 var day = date.getDate() var hour = date.getHours() var minute = date.getMinut

  • js时间戳转yyyy-MM-dd HH-mm-ss工具类详解

    在web开发中,我们经常需要用js将时间戳转yyyy-MM-dd HH-mm-ss类似的格式,这样才适合我们的观感,那么我们该如何在js中将时间戳转换成这种格式呢?其实很简单,我们开发一个时间戳工具类,如下: 第一种:最简单的是一个js时间格式的转换函数方法 function formatDateTime(inputTime) { var date = new Date(inputTime); var y = date.getFullYear(); var m = date.getMonth()

  • Java TimedCache 带时间缓存工具类详解使用

    简述 我们在工作中会碰到需要使用带过期时间的缓存场景.但是使用redis有太重了,毕竟缓存的数据很小,放在内存够够的.hutools提供了TimedCache时间缓存工具,可以实现该场景.下面使用到该组件,并为了适配工作场景,对该工具类做优化升级. Maven依赖 <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>

  • python 提取视频中的音频工具类详解

    前言 利用Python的ffmpy库提取视频中的音频.本文提供工具类代码. 环境依赖 需要安装ffmpy,安装指令: pip install ffmpy -i https://pypi.douban.com/simple 工具代码 不废话,上代码. #!/user/bin/env python # coding=utf-8 """ @project : csdn @author : huyi @file : extract_audio_from_audio.py @ide :

  • Springboot Mybatis Plus自动生成工具类详解代码

    前言 代码生成器,也叫逆向工程,是根据数据库里的表结构,自动生成对应的实体类.映射文件和接口. 看到很多小伙伴在为数据库生成实体类发愁,现分享给大家,提高开发效率. 一.pom依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.1</version> &

  • PHP用PDO如何封装简单易用的DB类详解

    前言 PDO扩展为PHP访问数据库定义了一个轻量级的.一致性的接口,它提供了一个数据访问抽象层,这样,无论使用什么数据库,都可以通过一致的函数执行查询和获取数据.PDO随PHP5.1发行,在PHP5.0的PECL扩展中也可以使用. 我个人理解:PDO是一个抽象类,为我们提供访问数据的接口方法,下面这篇将给大家介绍关于PHP如何利用PDO封装简单易用的DB类,下面话不多说,来一起看看详细的介绍: 使用 创建测试库和表 create database db_test; CREATE TABLE `u

  • Android手机管理工具类详解

    Android手机管理工具类 AppPhoneMgr分享给大家,供大家参考,具体内容如下 工具类内的方法: getInstance          : 单例对象 getSDKVersionNumber  : 获取手机系统版本号 getPhoneModel        : 获取手机型号 getPhoneWidth        : 获取手机宽度 getPhoneHeight       : 获取手机高度 getPhoneImei         : 获取手机imei串号 ,GSM手机的 IME

随机推荐