如何自定义iOS通讯录
苹果给用户提供了自己的通讯录,但是根据业务的需求,需要自定义通讯录,我们就需要根据业务需求来自定义。
首先我们需要知道苹果的提供的一些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
rypersoninfo.h
#import <foundation/foundation.h> #import <addressbook/addressbook.h> @interface rypersoninfo : nsobject /** * 单值信息 */ #define property_str_readonly(name) @property (nonatomic, copy) nsstring *name; // 姓 property_str_readonly(firstname) // 名 property_str_readonly(lastname) // 中间名 property_str_readonly(middlename) // 全名 property_str_readonly(fullname) // 搜索索引 property_str_readonly(firstspell) // 前缀 property_str_readonly(prefix) // 后缀 property_str_readonly(suffix) // 昵称 property_str_readonly(nickname) // 姓_音标 property_str_readonly(firstnamephonetic) // 名_音标 property_str_readonly(lastnamephonetic) // 中间名_音标 property_str_readonly(middlenamephonetic) // 公司 property_str_readonly(organization) // 工作 property_str_readonly(jobtitle) // 部门 property_str_readonly(department) // 生日 property_str_readonly(birthday) // 备忘录 property_str_readonly(note) // 第一次创建用户信息的时间 property_str_readonly(firstknow) // 最后一次更改用户信息的时间 property_str_readonly(lastknow) // 名片类型(company/person) property_str_readonly(kind) // 多值信息 #define property_arr_readonly(name) @property (nonatomic, strong) nsarray *name; // 邮箱 property_arr_readonly(email) // 地址 property_arr_readonly(address) // 日期 property_arr_readonly(dates) // imessage property_arr_readonly(imessage) // 电话号码 property_arr_readonly(phone) // url链接 property_arr_readonly(url) #define property_img_readonly(name) @property (nonatomic, strong) uiimage *name; // 图片 //property_img_readonly(image) /** * 初始化方法 * * @param ref 联系人属性 * * @return 实例对象 */ - (id)initwithabrecordref:(abrecordref)ref; /** * 初始化类方法 * * @param ref 联系人属性 * * @return 实例对象 */ + (id)personinfowithabrecordref:(abrecordref)ref; @end
rypersoninfo.m
#import "rypersoninfo.h" #define nullstrtoempty(str) \ [str rangeofstring:@"null"].location==0? @"" : str /** * 单值信息 */ #define get_property_method(property, property_key) \ - (nsstring *)property {\ return (nsstring *)cfbridgingrelease(abrecordcopyvalue(_recordref, property_key));\ } /** * 多值信息 */ #define dict_add_str_for_key(dict, str, key) \ if (str) {\ [dict setobject:str forkey:key];\ } #define get_property_sigle_value_method(property, property_key)\ - (nsarray *)property\ {\ nsmutablearray *rtnarray = [nsmutablearray array];\ \ abmultivalueref ref = abrecordcopyvalue(_recordref, property_key);\ long count = abmultivaluegetcount(ref);\ for (int i = 0; i < count; i++)\ {\ nsstring* label = (__bridge nsstring*)abaddressbookcopylocalizedlabel(abmultivaluecopylabelatindex(ref, i));\ nsstring* content = (__bridge nsstring*)abmultivaluecopyvalueatindex(ref, i);\ nsmutabledictionary *dict = [nsmutabledictionary dictionary];\ dict_add_str_for_key(dict, content, label);\ \ [rtnarray addobject:dict];\ }\ return rtnarray;\ } @interface rypersoninfo () @property (nonatomic , assign)abrecordref recordref; @end @implementation rypersoninfo - (id)initwithabrecordref:(abrecordref)ref { if (self = [super init]) { _recordref = ref; } return self; } + (id)personinfowithabrecordref:(abrecordref)ref { return [[[self class] alloc] initwithabrecordref:ref]; } get_property_method( firstname , kabpersonfirstnameproperty); get_property_method( lastname , kabpersonlastnameproperty); get_property_method( middlename , kabpersonmiddlenameproperty); get_property_method( prefix , kabpersonprefixproperty); get_property_method( suffix , kabpersonsuffixproperty); get_property_method( nickname , kabpersonnicknameproperty); get_property_method( organization , kabpersonorganizationproperty); get_property_method( jobtitle , kabpersonjobtitleproperty); get_property_method( department , kabpersondepartmentproperty); get_property_method( birthday , kabpersonbirthdayproperty); get_property_method( note , kabpersonnoteproperty); get_property_method( firstknow , kabpersoncreationdateproperty); get_property_method( lastknow , kabpersonmodificationdateproperty); get_property_method( firstnamephonetic , kabpersonfirstnamephoneticproperty); get_property_method( lastnamephonetic , kabpersonlastnamephoneticproperty); get_property_method( middlenamephonetic, kabpersonmiddlenamephoneticproperty); get_property_sigle_value_method(email, kabpersonemailproperty) get_property_sigle_value_method(dates, kabpersondateproperty) get_property_sigle_value_method(url , kabpersonurlproperty) get_property_sigle_value_method(phone, kabpersonphoneproperty) - (nsstring *)kind { nsstring *rtnstr = nil; cfnumberref recordtype = abrecordcopyvalue(_recordref, kabpersonkindproperty); if (recordtype == kabpersonkindorganization) { rtnstr = @"company"; } else { rtnstr = @"person"; } return rtnstr; } - (nsarray *)imessage { nsmutablearray *rtnarray = [nsmutablearray array]; abmultivalueref instantmessage = abrecordcopyvalue(_recordref, kabpersoninstantmessageproperty); for (int i = 1; i < abmultivaluegetcount(instantmessage); i++) { nsstring* label = (__bridge nsstring*)abmultivaluecopylabelatindex(instantmessage, i); nsdictionary* content =(__bridge nsdictionary*) abmultivaluecopyvalueatindex(instantmessage, i); nsmutabledictionary *imessageinfodict = [nsmutabledictionary dictionary]; nsstring* username = [content valueforkey:(nsstring *)kabpersoninstantmessageusernamekey]; nsstring* service = [content valueforkey:(nsstring *)kabpersoninstantmessageservicekey]; dict_add_str_for_key(imessageinfodict, username, @"username"); dict_add_str_for_key(imessageinfodict, service, @"service"); nsdictionary *imessagedict = @{label: imessageinfodict}; [rtnarray addobject:imessagedict]; } return rtnarray; } -(nsarray *)address { nsmutablearray *rtnarray = [nsmutablearray array]; abmultivalueref address = abrecordcopyvalue(_recordref, kabpersonaddressproperty); long count = abmultivaluegetcount(address); for(int i = 0; i < count; i++) { nsstring* addresslabel = (__bridge nsstring*)abmultivaluecopylabelatindex(address, i); nsdictionary* personaddress =(__bridge nsdictionary*) abmultivaluecopyvalueatindex(address, i); nsmutabledictionary *addressinfodict = [nsmutabledictionary dictionary]; nsstring* country = [personaddress valueforkey:(nsstring *)kabpersonaddresscountrykey]; nsstring* city = [personaddress valueforkey:(nsstring *)kabpersonaddresscitykey]; nsstring* state = [personaddress valueforkey:(nsstring *)kabpersonaddressstatekey]; nsstring* street = [personaddress valueforkey:(nsstring *)kabpersonaddressstreetkey]; nsstring* zip = [personaddress valueforkey:(nsstring *)kabpersonaddresszipkey]; nsstring* coutntrycode = [personaddress valueforkey:(nsstring *)kabpersonaddresscountrycodekey]; dict_add_str_for_key(addressinfodict, country, @"country"); dict_add_str_for_key(addressinfodict, city, @"city"); dict_add_str_for_key(addressinfodict, state, @"state"); dict_add_str_for_key(addressinfodict, street, @"street"); dict_add_str_for_key(addressinfodict, zip, @"zip"); dict_add_str_for_key(addressinfodict, coutntrycode, @"coutntrycode"); nsdictionary *addressdict = @{addresslabel: addressinfodict}; [rtnarray addobject:addressdict]; } return rtnarray; } //- (uiimage *)image //{ // nsdata *data = (__bridge nsdata*)abpersoncopyimagedata(_recordref); // return [uiimage imagewithdata:data]; //} #pragma mark - #pragma mark - customproperty /** * 全名 */ - (nsstring *)fullname { return [nsstring stringwithformat:@"%@%@%@", nullstrtoempty(self.lastname), nullstrtoempty(self.middlename), nullstrtoempty(self.firstname)]; } /** * 首字母 */ - (nsstring *)firstspell { return getfirstspell(self.fullname); } /** * 输出模型所有信息 */ - (nsstring *)description { return [nsstring stringwithformat:@"%@ -- infopacket", self.fullname]; } /** * 获取首字母 */ nsstring* getfirstspell(nsstring *fullname) { nsmutablestring *ms = [[nsmutablestring alloc] initwithstring:fullname]; cfstringtransform((__bridge cfmutablestringref)ms, 0, kcfstringtransformmandarinlatin, no); cfstringtransform((__bridge cfmutablestringref)ms, 0, kcfstringtransformstripdiacritics, no); if (fullname.length > 0) return [[ms substringwithrange:nsmakerange(0, 1)] lowercasestring]; else return @"#"; } @end
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。