当前位置: 首页 > 编程日记 > 正文

关于IOS获取本地通讯录信息(包含iOS9.0前后)

在ios开发当中,获取用户本地的通讯录功能愈加频繁的出现,七两自己也在自己公司的项目当中遇到的获取本地的通讯录信息的功能(俗称“种子用户功能”,太可怕了)。对此七两总结了自己使用本地通讯录时的注意点,希望对大家有所帮助。

首先对于获取本地通讯录的信息,大苹果在ios9.0之后推出了另外的一个使用方式(controller),类似于之前searchcontroller与searchBar,对此七两在此分成两部分,ios9.0前与ios9.0后两部分进行总结。


一、iOS9.0前

先附上七两自己写得代码:
对于苹果对于通讯录的操作实现可以类比sqlite与sqlite3的管理实现方式,及我们在使用通讯录时需调用类似于sqlite3的管理对象,对此七两自己习惯将对通讯录的操作过程写成单例,具体如下:

.h文件
[objc] view plaincopy
  1. #import <Foundation/Foundation.h>  
  2. #import <AddressBook/AddressBook.h>  
  3. #import <UIKit/UIKit.h>  
  4.   
  5. typedef void(^YFAddressBookBlock)(BOOL canRead, ABAuthorizationStatus authorStatus);  
  6.   
  7. @interface YFAddressBookManger : NSObject  
  8.   
  9. @property (nonatomic, assign) ABAddressBookRef addressBook;  
  10. //单例类方法  
  11. + (instancetype)shareManger;  
  12.   
  13. //设置传值  
  14. - (void)canReadAddressBookWithBlock:(YFAddressBookBlock)block;  
  15.   
  16. - (void)gotoSetting:(UIViewController *)vc;  
  17.   
  18. @end  

.m文件

[objc] view plaincopy
  1. #import "YFAddressBookManger.h"  
  2.   
  3. @implementation YFAddressBookManger  
  4.   
  5. + (instancetype)shareManger{  
  6.     static YFAddressBookManger *manger = nil;  
  7.   
  8.     static dispatch_once_t onceToken;  
  9.     dispatch_once(&onceToken, ^{  
  10.         if (!manger) {  
  11.             manger = [[YFAddressBookManger alloc]init];  
  12.         }  
  13.     });  
  14.     return manger;  
  15. }  
  16.   
  17. - (id)init{  
  18.     self = [super init];  
  19.     if (self) {  
  20.         _addressBook = ABAddressBookCreateWithOptions(NULLNULL);  
  21.     }  
  22.       
  23.     return self;  
  24. }  
  25.   
  26. //获取读取权限  
  27. - (void)canReadAddressBookWithBlock:(YFAddressBookBlock)block{  
  28.     ABAuthorizationStatus authStatus = ABAddressBookGetAuthorizationStatus();  
  29.     if (authStatus == kABAuthorizationStatusNotDetermined) {  
  30.         ABAddressBookRequestAccessWithCompletion(_addressBook, ^(bool granted, CFErrorRef error) {  
  31.            dispatch_async(dispatch_get_main_queue(), ^{  
  32.                if (error) {  
  33.                    //拒绝访问  
  34.                    block(NO,kABAuthorizationStatusDenied);  
  35.                }else{  
  36.                    block(YES,0);  
  37.                }  
  38.            });  
  39.         });  
  40.     }else if (authStatus == kABAuthorizationStatusAuthorized){  
  41.         block(YES,0);  
  42.     }else{  
  43.         block(NO,authStatus);  
  44.     }  
  45. }  
  46.   
  47. //去设置页面  
  48. - (void)gotoSetting:(UIViewController *)vc{  
  49.     NSString *appName = [[NSBundle mainBundle].infoDictionary valueForKey:@"CFBundleDisplayName"];  
  50.     if (!appName) appName = [[NSBundle mainBundle].infoDictionary valueForKey:@"CFBundleName"];  
  51.     NSString *message = [NSString stringWithFormat:@"请在%@的\"设置-隐私-通讯录\"选项中,\r允许%@访问你的通讯录。",[UIDevice currentDevice].model,appName];  
  52.   
  53.     UIAlertController *alertVC = [[UIAlertController alloc]init];  
  54.     [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];  
  55.     UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {  
  56.         [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];  
  57.     }];  
  58.     UIAlertAction *cancleAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {  
  59.           
  60.     }];  
  61.     [alertVC addAction:cancleAction];  
  62.     [alertVC addAction:sureAction];  
  63. }  
  64. @end  

后续引用通讯录中得数据至controller中的使用方式如下:
[objc] view plaincopy
  1. #pragma mark - 获取本地的通讯录数据  
  2. - (void)getDataSource{  
  3.     if (_dataSource == nil) {  
  4.         _dataSource = [NSMutableArray new];  
  5.     }  
  6.     [[YFAddressBookManger shareManger]canReadAddressBookWithBlock:^(BOOL canRead, ABAuthorizationStatus authorStatus) {  
  7.         if (canRead) {  
  8.             ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULLNULL);  
  9.             CFArrayRef allLinkPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);  
  10.             CFIndex num = ABAddressBookGetPersonCount(addressBook);  
  11.             for (NSInteger i = 0; i < num; i++) {  
  12.                 ABRecordRef  people = CFArrayGetValueAtIndex(allLinkPeople, i);  
  13.                 ABMultiValueRef phones = ABRecordCopyValue(people, kABPersonPhoneProperty);  
  14.                   
  15.                 for (int k = 0; k<ABMultiValueGetCount(phones); k++)  
  16.                 {  
  17.                     //获取該Label下的电话值  
  18.                     NSString * personPhone = (__bridge NSString*)ABMultiValueCopyValueAtIndex(phones, k);  
  19.                       
  20.                     NSString *newP = [personPhone stringByReplacingOccurrencesOfString:@" " withString:@""];  
  21.                     newP = [newP stringByReplacingOccurrencesOfString:@"-" withString:@""];  
  22.                       
  23.                     // 去除+86  
  24.                     if ([newP containsString:@"+86"]) {  
  25.                         newP = [newP stringByReplacingOccurrencesOfString:@"+86" withString:@""];  
  26.                     }  
  27.                     // 去除+  
  28.                     if ([newP containsString:@"+"]) {  
  29.                         newP = [newP stringByReplacingOccurrencesOfString:@"+" withString:@""];  
  30.                     }  
  31.                     if (![_dataSource containsObject:newP]) {  
  32.                         [_dataSource addObject:newP];  
  33.                     }  
  34.                 }  
  35.                   
  36.             }  
  37.   
  38.         }else{  
  39.             [[YFAddressBookManger shareManger] gotoSetting:self];  
  40.         }  
  41.     }];  
  42. }  
如果需要其余的多余的单值属性需不同的字段,代码中的ABRecordCopyValue方法可以理解为C语言中得字典。即可根据不同的单值属性获取。

二、iOS9.0之后

苹果推荐ContactsUI使用,具体的使用方式如下:

[objc] view plaincopy
  1. pragma mark - <CNContactPickerViewController代理方法>  
  2. /* 当选中一个联系人时,会执行该方法  
  3. @param picker 选择联系人的控制器  
  4. @param contact 选择的联系人 / 
  5. (void)contactPicker:(CNContactPickerViewController )picker didSelectContact:(CNContact )contact{ 
  6. // 1.获取联系人的姓名   NSString *firstName = contact.givenName; 
  7.   NSString *lastName = contact.familyName; 
  8.   NSLog(@"%@ %@", firstName, lastName); 
  9. // 2.获取联系人的电话号码   NSArray *phoneNumers = contact.phoneNumbers; 
  10.    for (CNLabeledValue *labelValue in phoneNumers) { 
  11.        CNPhoneNumber *phoneNumber = labelValue.value;  
  12.        NSString *phoneValue = phoneNumber.stringValue;  
  13.        NSString *phoneLabel = labelValue.label; 
  14.        NSLog(@"%@ %@", phoneValue, phoneLabel); 
  15.   } 
  16. } 
  17. /* 当选中某一个联系人的某一个属性时,会执行该方法  
  18. @param contactProperty 选中的联系人属性 
  19. */  
  20. (void)contactPicker:(CNContactPickerViewController )picker didSelectContactProperty:(CNContactProperty )contactProperty{}  


具体的细节使用如下:


[objc] view plaincopy
  1. // 1.获取授权状态  
  2. CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];  
  3. // 2.如果不是已经授权,则直接返回  
  4. if (status != CNAuthorizationStatusAuthorized) return;  
  5.   
  6. // 3.获取联系人  
  7. // 3.1.创建联系人仓库  
  8. CNContactStore *store = [[CNContactStore alloc] init];  
  9.   
  10. // 3.2.创建联系人的请求对象  
  11. // keys决定这次要获取哪些信息,比如姓名/电话  
  12. NSArray *fetchKeys = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];  
  13. CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:fetchKeys];  
  14.   
  15. // 3.3.请求联系人  
  16. NSError *error = nil;  
  17. [store enumerateContactsWithFetchRequest:request error:&error usingBlock:^(CNContact * _Nonnull contact, BOOLBOOL * _Nonnull stop) {  
  18.     // stop是决定是否要停止  
  19.     // 1.获取姓名  
  20.     NSString *firstname = contact.givenName;  
  21.     NSString *lastname = contact.familyName;  
  22.     NSLog(@"%@ %@", firstname, lastname);  
  23.   
  24.     // 2.获取电话号码  
  25.     NSArray *phones = contact.phoneNumbers;  
  26.   
  27.     // 3.遍历电话号码  
  28.     for (CNLabeledValue *labelValue in phones) {  
  29.         CNPhoneNumber *phoneNumber = labelValue.value;  
  30.         NSLog(@"%@ %@", phoneNumber.stringValue, labelValue.label);  
  31.     }  
  32. }];  

相关文章:

C和C++安全编码笔记:动态内存管理

4.1 C内存管理&#xff1a; C标准内存管理函数&#xff1a; (1).malloc(size_t size)&#xff1a;分配size个字节&#xff0c;并返回一个指向分配的内存的指针。分配的内存未被初始化为一个已知值。 (2).aligned_alloc(size_t alignment, size_t size)&#xff1a;为一个对象…

作为一名程序员,数学到底对你有多重要?

最近在知乎上看到一个贴子&#xff0c;看完后我沉默了.....沉思后想想&#xff0c;其实每个行业都会分等级&#xff0c;程序员也不例外&#xff01;说好听一点的叫工程师&#xff0c;普通一点的叫程序员&#xff0c;差一点的叫码农&#xff0c;更差的还会叫码畜&#xff0c;码奴…

经典SQL(sqlServer)

一、基础 1、说明&#xff1a;创建数据库CREATE DATABASE database-name 2、说明&#xff1a;删除数据库drop database dbname3、说明&#xff1a;备份sql server--- 创建 备份数据的 deviceUSE masterEXEC sp_addumpdevice disk, testBack, c:\mssql7backup\MyNwind_1.dat--- …

iOS UITextField输入框随键盘弹出界面上移

//点击输入框界面跟随键盘上移 - (void)textFieldDidBeginEditing:(UITextField *)textField { CGRect frame textField.frame; int offSet frame.origin.y 70 - (self.view.frame.size.height - 216.0); //iphone键盘高度为216.iped键盘高度为352 [UIView beginAnimations:…

IEEE分享 | 机器学习在领英的规模化应用

人工智能和机器学习仍然是全球持续增长的领域之一&#xff0c;近年来涌现出越来越多本科生或者非人工智能专业出身的工程师&#xff0c;他们努力学习和使用技术来改进产品&#xff0c;几乎每天都有新的机器学习技术和框架发布。这篇文章将讨论领英如何规模化利用技术&#xff0…

GitHub/GitLab/Gitee中项目互拷贝后仍保留历史提交记录的方法

GitHub、GitLab、Gitee等在同一个网站中执行复制或拷贝一个已有项目到一个新项目比较简单&#xff0c;因为它们在每一个项目上都有一个Fork按钮&#xff0c;直接点击此Fork按钮即可&#xff0c;Fork后的新项目会保留原有项目的历史提交记录。但是如果不在同一个网站上进行此操作…

基于mimeTex的数学公式Webservice的部署和实现

通过Latex语法&#xff0c;实现生成数学公式的解决方案也很多。这里介绍一种方法&#xff0c;使用开源的mimeTex。该项目的官网地址如下&#xff1a;http://www.forkosh.com/mimetex.html网站主页有一个声明。如果你的服务器上已经安装了latex&#xff0c;那么推荐使用mathTex&…

对称加密算法AES之GCM模式简介及在OpenSSL中使用举例

AES(Advanced Encryption Standard)即高级加密标准&#xff0c;由美国国家标准和技术协会(NIST)于2000年公布&#xff0c;它是一种对称加密算法。关于AES的更多介绍可以参考&#xff1a;https://blog.csdn.net/fengbingchun/article/details/100139524 AES的GCM(Galois/Counte…

iOS UITextField清空按钮

extField.clearButtonModeUITextFieldViewModeWhileEditing; 就可以了&#xff0c;表明编辑输入框的时候启动一键清空按钮。另外&#xff0c;clearButtonMode还有三个属性&#xff1a; UITextFieldViewModeNever, 清空按钮永不出现 UITextFieldViewModeUnlessEditing, 不编…

腾讯“疯狂”开源

作者 | 马超责编 | 胡巍巍出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;近日&#xff0c;腾讯自研的万亿级分布式消息中间件TubeMQ正式开源&#xff0c;并捐赠给Apache基金会&#xff0c;成为基金会官方认可的Incubator项目。我们知道与TubeMQ功能类似的kafka是领…

[Android]开发摇一摇分歧表决器过程

心血来潮&#xff0c;走进Android&#xff0c;准备开发一个摇一摇分歧表决器&#xff08;PS&#xff1a;这个想法源自去年看的一个都市剧《约会专家》中主人公杭杭开发的分歧表决器APP&#xff09;。简述&#xff1a;摇一摇分歧表决器是一款Android App&#xff0c;通过将传统的…

C和C++安全编码笔记:整数安全

5.1 整数安全导论&#xff1a;整数由包括0的自然数(0, 1, 2, 3, …)和非零自然数的负数(-1, -2, -3, …)构成。 5.2 整数数据类型&#xff1a;整数类型提供了整数数学集合的一个有限子集的模型。一个具有整数类型的对象的值是附着在这个对象上的数学值。一个具有整数类型的对象…

8.3折特惠票仅剩3天!「2019 嵌入式智能国际大会」全日程大公开!

8.3折特惠票仅剩3天立即抢购&#xff1a;https://t.csdnimg.cn/otBk还有5天&#xff0c;大伙期待的「2019嵌入式智能国际大会」正式开幕了&#xff01;2019年12月6日-7日&#xff0c;我们在深圳市人才研修院见&#xff01;大会以“万物互联泛在智能”为主题&#xff0c;邀请30位…

iOS点击空白收回键盘

//点击空白收回键盘 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self.view endEditing:YES]; }

第一个net-mvc程序

结构 视图层 <% Page Language"C#" Inherits"System.Web.Mvc.ViewPage<dynamic>" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">…

iOS 储存用户信息设置封装 直接调用即可(部分是代码片段)

、、、、、、、、、、、、、、、、、、首先 定义 UserInfo #import <Foundation/Foundation.h> interface UserInfo : NSObject //用户id property (nonatomic, strong) NSString *userID; //用户名 property (nonatomic, strong) NSString *userName; //密码 propert…

ASN.1简介及OpenSSL中ASN.1接口使用举例

ASN.1(Abstract Syntax Notation One)是一套标准&#xff0c;是描述数据的表示、编码传输、解码的灵活的记法。它提供了一套正式、无歧义和精确的规则以描述独立于特定计算机硬件的对象结构。OpenSSL的编码方法就是基于该标准。ASN.1是一种结构化的数字对象描述语言&#xff0c…

谁是当今最顶级的技术?SQL、Java、Python、C++ 皆上榜!

【12月公开课预告】&#xff0c;入群直接获取报名地址12月11日晚8点直播主题&#xff1a;人工智能消化道病理辅助诊断平台——从方法到落地12月12日晚8点直播&#xff1a;利用容器技术打造AI公司技术中台12月17日晚8点直播主题&#xff1a;可重构计算&#xff1a;能效比、通用性…

将表里的数据批量生成INSERT语句的存储过程 增强版

原文:将表里的数据批量生成INSERT语句的存储过程 增强版将表里的数据批量生成INSERT语句的存储过程 增强版 有时候&#xff0c;我们需要将某个表里的数据全部或者根据查询条件导出来&#xff0c;迁移到另一个相同结构的库中 目前SQL Server里面是没有相关的工具根据查询条件来生…

通过OpenSSL的接口实现Base64编解码

对openssl genrsa产生的rsa私钥pem文件&#xff0c;使用普通的base64解码会有问题&#xff0c;如使用https://blog.csdn.net/fengbingchun/article/details/85218653 中介绍的方法&#xff0c;一是有可能不能从返回的结果中直接使用strlen来获得最终字符的大小&#xff0c;因为…

激辩:机器究竟能否理解常识?

【12月公开课预告】&#xff0c;入群直接获取报名地址12月11日晚8点直播主题&#xff1a;人工智能消化道病理辅助诊断平台——从方法到落地12月12日晚8点直播&#xff1a;利用容器技术打造AI公司技术中台12月17日晚8点直播主题&#xff1a;可重构计算&#xff1a;能效比、通用性…

Mac OS X 下Node.js开发环境的搭建

1.安装Xcode2.安装Homebrew 谷歌搜索Homebrew 复制命令行 打开终端 粘贴命令行 点击回车 安装 输入密码等2.安装Nodejs利用Homebrew安装nodejs打开终端 输入 &#xff1a;brew install nodejs 回车查询nodejs版本&#xff1a;node --version3.安装文档数据库 MongoDB打开终…

.NET 使用 MySql.Data.dll 动态库操作MySql的帮助类--MySqlHelper

.NET 使用 MySql.Data.dll 动态库操作MySql的帮助类--MySqlHelper 參考演示样例代码&#xff0c;例如以下所看到的&#xff1a; /// <summary>/// MySql 数据库操作类/// </summary>public class MySqlHelper{/// <summary>/// MysqlConnection/// </summ…

Instagram个性化推荐工程中三个关键技术是什么?

作者 | Ivan Medvedev&#xff0c;Haotian Wu&#xff0c;Taylor Gordon译者 | 陆离编辑 | Jane出品 | AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09; 【导语】近期&#xff0c;Facebook 在博客上分享了第一篇详细介绍 Explore 系统关键技术&#xff0c;以及 I…

iOS UIbutton 点击无反应的几种情况

1、UIButton不能点击情况的第一种是&#xff0c;你将button添加到一个不能响应点击事件的View里。如你将button添加到UIImageView中&#xff0c;解决办法只需将UIImageView的 userInteractionEnabled设为YES即可。 例如&#xff1a; self.headImgV [[UIImageView alloc] ini…

C和C++安全编码笔记:格式化输出

C标准中定义了一些可以接受可变数量参数的格式化输出参数&#xff0c;参数中包括一个格式字符串。printf()和sprintf()都是格式化输出函数的例子。格式化输出函数是由一个格式字符串和可变数目的参数构成的。在效果上&#xff0c;格式化字符串提供了一组可以由格式化输出函数解…

谈谈UI架构设计的演化

谈谈UI架构设计的演化 经典MVC 在1979年&#xff0c;经典MVC模式被提出。 在当时&#xff0c;人们一直试图将纯粹描述思维中的对象与跟计算机环境打交道的代码隔离开来&#xff0c;而Trygve Reenskaug在跟一些人的讨论中&#xff0c;逐渐剥离出一系列的概念&#xff0c;最初是T…

JWT(JSON Web Token)简介及实现

JWT(JSON Web Token)&#xff1a;是一个开放标准(RFC 7519)&#xff0c;它定义了一种紧凑且自包含的方式&#xff0c;用于在各方之间作为Json对象安全地传输信息。由于此信息是经过数字签名的&#xff0c;因此可以被验证和信任。可以使用HMAC SHA256或RSA等对JWT进行签名。 JW…

iOS UIImageView 加载含有汉字的url处理方法

NSString *url [model.pic stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; [self.headImgView sd_setImageWithURL:[NSURL URLWithString:url]];

《评人工智能如何走向新阶段》后记

由AI科技大本营下载自视觉中国自《评人工智能如何走向新阶段》一文发表&#xff08;在内部&#xff09;后&#xff0c;引来了中外专家、草根们的广泛议论&#xff0c;有深有浅&#xff0c;其中似有一些思考价值&#xff0c;故录入本文后记&#xff1a; 中外专家、草根们23条议…