自定义iOS通讯录

来源:互联网 发布:java教程菜鸟教程 编辑:程序博客网 时间:2024/05/29 04:55

苹果给用户提供了自己的通讯录,但是根据业务的需求,需要自定义通讯录,我们就需要根据业务需求来自定义 

首先我们需要知道苹果的提供的一些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 RYAddressBookNSString* 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)// iMessagePROPERTY_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





2 0
原创粉丝点击