调用系统通讯录
2016-01-11 15:43
330 查看
通常我们在iOS项目中想到通讯录往往有两大方面的需求。一个是让用户自己从通讯录中选择朋友然后我们获取数据完成业务,另一个是项目通过读取用户通讯录信息来完成相应的数据处理,即用户自主行为和应用调取行为。
首先谈一下用户自主调用通讯录。这里我们会使用系统控件ABPeoplePickerNavigationController。由于是用户自主行为,调用它我们无须向用户请求授权。但是ABPeoplePickerNavigationController给我们提供的操作很有限,在界面上我们只能修改一下导航条背景色,标题颜色之类的属性。对我们更有用的数据则是通过ABPeoplePickerNavigationControllerDelegate的相关方法完成的。这里注意一下,iOS8替换了一个代理方法
这也是我们获取数据的主要代理方法。此方法可以看到我们唯一可以获得可操作的数据就是(ABRecordRef)person。下面是获取person数据中手机号的实现:
再谈谈应用调取通讯录信息的方式。这里我们需要让用户授权应用调取通讯录的权限,这样我们可以对通讯录进行增删改查操作。具体的,我们使用ABAddressBookRef和其相关的一系列类。注意,他们都不是iOS类,不支持现金常用的ARC自动管理内存,所以要特别注意内存问题,防止内存泄露。
这里结合韩韩自身的实际应用,谈谈这种调用通讯录的方法。我的目的是读取通讯录,根据已有的手机号码数据查找相应的用户名,然后显示。在ABAddressBookRef系列类中有根据名字查找通讯录单元信息(ABRecordRef)的方法,但是恰好没有根据手机号查找通讯录单元信息的方法。那么只能通过获得通讯录全部信息,然后遍历并比对手机号信息来查找了。
1)询问用户获得通讯录读取权限:
2)获取全部通讯录单元信息(ABRecordRef)
3)获取全部通讯录单元信息(获取名字)
4)获取全部通讯录单元信息(获取手机号)
剩下的就是比对和数据处理了。运用ABAddressBookRef还可以实现写入数据、删除数据的功能。待以后进一步研究。
在iOS9系统中,新发现关于通讯录的问题。现象,在调用通讯录的页面,当打开通讯录正常点选某条电话信息后关闭通讯录之后,在某些页面获取当前最上层window的时候,发现获取到了如
remoteKeyWindow 的一个window,为iOS9新发现的状况,这会造成一些window操作的错误。且到现在为止未查到相关资料。为了降低影响,采取了非根本的方式解决,即在关闭通讯录时,取一个当前页面的textField,在关闭通讯录之后取消该textField的第一响应者。经实测,问题得到了解决。但究其根本原因还不知晓。
首先谈一下用户自主调用通讯录。这里我们会使用系统控件ABPeoplePickerNavigationController。由于是用户自主行为,调用它我们无须向用户请求授权。但是ABPeoplePickerNavigationController给我们提供的操作很有限,在界面上我们只能修改一下导航条背景色,标题颜色之类的属性。对我们更有用的数据则是通过ABPeoplePickerNavigationControllerDelegate的相关方法完成的。这里注意一下,iOS8替换了一个代理方法
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person NS_AVAILABLE_IOS(8_0);
这也是我们获取数据的主要代理方法。此方法可以看到我们唯一可以获得可操作的数据就是(ABRecordRef)person。下面是获取person数据中手机号的实现:
NSString* name = (__bridge_transfer NSString*)ABRecordCopyCompositeName(person); //获取联系人电话 ABMutableMultiValueRef phoneMulti = ABRecordCopyValue(person, kABPersonPhoneProperty); NSMutableArray *phones = [[NSMutableArray alloc] init]; int i; for (i = 0; i < ABMultiValueGetCount(phoneMulti); i++) { NSString *aPhone = (__bridge_transfer NSString*)ABMultiValueCopyValueAtIndex(phoneMulti, i); NSString *aLabel = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(phoneMulti, i); if (aPhone.length < 11) { break ; } if([aLabel isEqualToString:@"_$!<Mobile>!$_"]){ [phones addObject:[self reStringFormatter:aPhone]]; }else{ [phones addObject:[self reStringFormatter:aPhone]]; } } //解决phoneMulti的内存泄露 CFRelease(phoneMulti); //AB..... 类不支持ARC,需要手动内存管理,一定要注意内存!
再谈谈应用调取通讯录信息的方式。这里我们需要让用户授权应用调取通讯录的权限,这样我们可以对通讯录进行增删改查操作。具体的,我们使用ABAddressBookRef和其相关的一系列类。注意,他们都不是iOS类,不支持现金常用的ARC自动管理内存,所以要特别注意内存问题,防止内存泄露。
这里结合韩韩自身的实际应用,谈谈这种调用通讯录的方法。我的目的是读取通讯录,根据已有的手机号码数据查找相应的用户名,然后显示。在ABAddressBookRef系列类中有根据名字查找通讯录单元信息(ABRecordRef)的方法,但是恰好没有根据手机号查找通讯录单元信息的方法。那么只能通过获得通讯录全部信息,然后遍历并比对手机号信息来查找了。
1)询问用户获得通讯录读取权限:
if (ABAddressBookRequestAccessWithCompletion != NULL) { //检查是否是iOS6 ABAddressBookRef abRef = ABAddressBookCreateWithOptions(NULL, NULL); if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) { //如果该应用从未申请过权限,申请权限 ABAddressBookRequestAccessWithCompletion(abRef, ^(bool granted, CFErrorRef error) { //根据granted参数判断用户是否同意授予权限 if (granted) { //查询所有,这里我们可以用来进行下一步操作 } }); } else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) { //如果权限已经被授予 //查询所有,这里我们可以用来进行下一步操作 } else { //如果权限被收回,只能提醒用户去系统设置菜单中打开 } if(abRef){ CFRelease(abRef); } }
2)获取全部通讯录单元信息(ABRecordRef)
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL); //获取联系人电话 CFArrayRef allPerson = ABAddressBookCopyArrayOfAllPeople(addressBook);//取全部联系人
3)获取全部通讯录单元信息(获取名字)
ABRecordRef aPerson = CFArrayGetValueAtIndex(allPerson, (CFIndex)i); ABMutableMultiValueRef phoneMulti = ABRecordCopyValue(aPerson, kABPersonPhoneProperty); //按照汉语姓名规则拼接用户名,因为有前、中、后名,这里要注意 ABMutableMultiValueRef firstNameMulti = ABRecordCopyValue(aPerson, kABPersonFirstNameProperty); ABMutableMultiValueRef middleNameMulti = ABRecordCopyValue(aPerson, kABPersonMiddleNameProperty); ABMutableMultiValueRef lastNameMulti = ABRecordCopyValue(aPerson, kABPersonLastNameProperty); NSString *firsNameString = [self dealNullString:(__bridge_transfer NSString*)firstNameMulti]; NSString *middleNameString = [self dealNullString:(__bridge_transfer NSString*)middleNameMulti]; NSString *lastNameString = [self dealNullString:(__bridge_transfer NSString*)la NSString *nameString = [NSString stringWithFormat:@"%@%@%@",lastNameString,middleNameString,firsNameString]stNameMulti];
4)获取全部通讯录单元信息(获取手机号)
NSMutableArray *phones = [[NSMutableArray alloc] init]; for (int i = 0; i < ABMultiValueGetCount(phoneMulti); i++) { //phoneMulti 为ABMutableMultiValueRef类型 NSString *aPhone = (__bridge_transfer NSString*)ABMultiValueCopyValueAtIndex(phoneMulti, i); NSString *aLabel = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(phoneMulti, i); TBDPRINT(@"PhoneLabel:%@ Phone#:%@",aLabel,aPhone); if (aPhone.length < 11) { break ; } if([aLabel isEqualToString:@"_$!<Mobile>!$_"]){ [phones addObject:[self reStringFormatter:aPhone]]; }else{ [phones addObject:[self reStringFormatter:aPhone]]; } }
剩下的就是比对和数据处理了。运用ABAddressBookRef还可以实现写入数据、删除数据的功能。待以后进一步研究。
在iOS9系统中,新发现关于通讯录的问题。现象,在调用通讯录的页面,当打开通讯录正常点选某条电话信息后关闭通讯录之后,在某些页面获取当前最上层window的时候,发现获取到了如
remoteKeyWindow 的一个window,为iOS9新发现的状况,这会造成一些window操作的错误。且到现在为止未查到相关资料。为了降低影响,采取了非根本的方式解决,即在关闭通讯录时,取一个当前页面的textField,在关闭通讯录之后取消该textField的第一响应者。经实测,问题得到了解决。但究其根本原因还不知晓。
相关文章推荐
- nuget使用问题收集
- JAVA 使用Dom4j 解析XML
- JNDI是什么,有什么用
- 【类unix系统shell基础】1.08shell与进程
- 测频率
- SSL建立连接3
- sklearn 常用api(一)
- Spring调度
- sql语句基础-提升
- Vs2013安装python插件
- C#调用迅雷下载,调用迅雷影音播放
- Oracle DATABASE LINK(DBLINK)创建
- Java中堆内存和栈内存_在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)。修改栈指针就可以把栈中的内容销毁.这样最快
- struts2标签radio和select中listKey与listValue
- 使用WindowManager添加View——悬浮窗口的基本原理
- 读书笔记------android图片加载
- SSL建立连接2
- shell 脚本知识点
- 正则表达式在iOS中的运用
- 页面多个textField,键盘遮挡输入框的处理