苹果给用户提供了自己的通讯录,但是根据业务的需求,需要自定义通讯录,我们就需要根据业务需求来自定义。
首先我们需要知道苹果的提供的一些Foundation、UIKit框架,了解其中的一些特性,可以打开手机查看苹果系统提供的原生的通讯录,可以看到:
1.搜索框
2.右侧搜索条
3.联系人分组
4.添加联系人
5.获取联系人头像及联系方式
根据需求,可以总结出自定义通讯录需要做的一些功能,一项大的功能可以差分成一些小的功能,然后一个一个实现,将复杂的问题差分成小问题解决。
1.自定义搜索框
2.获取首字母
3.权限判断
4.排序
5.自定义搜索
6.自定义联系人界面(考虑多值的情况,获取通讯录头像)
简答介绍下排序:
IOS项目中会用到对通讯录的联系人或是会员按姓名为关键字排序,因为NSArray并不直接支持对汉字的排序,这就要通过将汉字转换成拼音完成按A~Z的排序,这看起来是个头疼的问题,因为牵扯到汉字转为拼音,获取汉字的首字的首字母,如将“王”变成“W”。
函数原理是:我们知道,在Objective C语言中,字符串是以unicode进行编码的。在unicode字符集中,汉字的编码范围为4E00 到 9FA5 之间(即从第19968开始的20902个字符是中文简体字符)。我们把这些字符的拼音首字母按照顺序都存放在一个char数组中。当我们查找一个汉字的拼音首字母时,只需把这个汉字的unicode码(即char强制转换为int)减去19968,然后用这个数字作为索引去找char数组中存放的字母即可。
给出项目的源码,注释很清楚。代码如:
RYAddressBook.h
#import <Foundation/Foundation.h>
#import "RYPersonInfo.h"
typedef void (^AddressBookBlock) (NSArray *personInfos);
@interface RYAddressBook : NSObject
/**
* 将数字转化为字母 0~26 1~25=a~z 26=#
*/
NSString* SpellFromIndex(int index);
/**
* 获取索引
*/
int Index(NSString *firstSpell);
/**
* 获取用户所有通讯录信息
*
* @return 所有通讯录数据信息数组
*/
+ (void)getPersonInfo:(AddressBookBlock)addressBookBlock;
/**
* 根据关键字匹配所有用户信息
*
* @param keyWord 匹配关键字
*
* @return 匹配到的通讯录数据信息数组
*/
+ (void)searchPersonInfo:(NSString *)keyWord addressBookBlock:(AddressBookBlock)addressBookBlock;
/**
* 根据姓名进行数组的重排序
*
* @param personInfos 获取的通讯录数据信息数组
*/
+ (NSArray *)sortPersonInfos:(NSArray *)personInfos;
@end
RYAddressBook.m
#import "RYAddressBook.h"
@interface RYAddressBook ()
@property (nonatomic, copy) AddressBookBlock addressBookBlock;
@end
@implementation RYAddressBook
NSString* SpellFromIndex(int index)
{
if (index == 26)
return @"#";
else
return [NSString stringWithFormat:@"%c", [@"A" characterAtIndex:0]+index];
}
int Index(NSString *firstSpell)
{
int i = [firstSpell characterAtIndex:0] - [@"a" characterAtIndex:0];
if ([firstSpell isEqualToString:@"#"] || i < 0 || i > 26) {
return 26;
}
return [firstSpell characterAtIndex:0] - [@"a" characterAtIndex:0];
}
/**
* 获取用户所有通讯录信息
*/
+ (void)getPersonInfo:(AddressBookBlock)addressBookBlock
{
[[self alloc] getPersonInfo:addressBookBlock];
}
/**
* 根据关键字匹配所有用户信息
*/
+ (void)searchPersonInfo:(NSString *)keyWord addressBookBlock:(AddressBookBlock)addressBookBlock
{
[[self alloc] searchPersonInfo:keyWord addressBookBlock:addressBookBlock];
}
/**
* 根据姓名进行数组的重排序
*/
+ (NSArray *)sortPersonInfos:(NSArray *)personInfos
{
return [[self alloc] sortPersonInfos:personInfos];
}
- (void)getPersonInfo:(AddressBookBlock)addressBookBlock
{
self.addressBookBlock = addressBookBlock;
[self searchPersonInfo:@""];
}
- (void)searchPersonInfo:(NSString *)keyWord addressBookBlock:(AddressBookBlock)addressBookBlock
{
self.addressBookBlock = addressBookBlock;
[self searchPersonInfo:keyWord];
}
- (NSArray *)sortPersonInfos:(NSArray *)personInfos
{
if (![personInfos isKindOfClass:[NSArray class]]) {
return nil;
}
NSMutableArray *arr = [NSMutableArray array];
for (int i = 0; i < 27; i++) {
[arr addObject:[NSMutableArray array]];
}
for (NSObject *obj in personInfos) {
if (![obj isKindOfClass:[RYPersonInfo class]]) {
continue;
}
RYPersonInfo *personInfo = (RYPersonInfo *)obj;
NSMutableArray *subArr = [arr objectAtIndex:Index(personInfo.firstSpell)];
[subArr addObject:personInfo];
}
return arr;
}
/**
* 根据关键字查询通讯录信息
*/
- (void)searchPersonInfo:(NSString *)keyWord
{
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
// 开始查询通讯录
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
if (granted) {
[self filterContentForSearchText:keyWord];
}
});
}
/**
* 开始匹配通讯录信息
*/
- (void)filterContentForSearchText:(NSString*)searchText
{
//如果没有授权则退出
if (ABAddressBookGetAuthorizationStatus() != kABAuthorizationStatusAuthorized) {
return;
}
NSArray *blockArray = [NSArray array];
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if([searchText length]==0)
{
//查询所有
blockArray = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
} else {
//条件查询
CFStringRef cfSearchText = (CFStringRef)CFBridgingRetain(searchText);
blockArray = CFBridgingRelease(ABAddressBookCopyPeopleWithName(addressBook, cfSearchText));
CFRelease(cfSearchText);
}
// 类型转换
blockArray = transformElements(blockArray);
// 返回BlockArray
self.addressBookBlock(blockArray);
}
/**
* 将所有元素转化为JXPersonInfo类型数组
*/
NSArray* transformElements(NSArray* arr)
{
NSMutableArray *rtnArray = [NSMutableArray array];
for (int i = 0; i < arr.count; i++) {
ABRecordRef recordRef = CFBridgingRetain([arr objectAtIndex:i]);
RYPersonInfo *personInfo = [RYPersonInfo personInfoWithABRecordRef:recordRef];
[rtnArray addObject:personInfo];
}
return rtnArray;
}
@end










