如何自定義iOS通訊錄
蘋果給用戶提供了自己的通訊錄,但是根據(jù)業(yè)務(wù)的需求,需要自定義通訊錄,我們就需要根據(jù)業(yè)務(wù)需求來自定義。
首先我們需要知道蘋果的提供的一些Foundation、UIKit框架,了解其中的一些特性,可以打開手機(jī)查看蘋果系統(tǒng)提供的原生的通訊錄,可以看到:
1.搜索框
2.右側(cè)搜索條
3.聯(lián)系人分組
4.添加聯(lián)系人
5.獲取聯(lián)系人頭像及聯(lián)系方式
根據(jù)需求,可以總結(jié)出自定義通訊錄需要做的一些功能,一項大的功能可以差分成一些小的功能,然后一個一個實(shí)現(xiàn),將復(fù)雜的問題差分成小問題解決。
1.自定義搜索框
2.獲取首字母
3.權(quán)限判斷
4.排序
5.自定義搜索
6.自定義聯(lián)系人界面(考慮多值的情況,獲取通訊錄頭像)
簡答介紹下排序:
IOS項目中會用到對通訊錄的聯(lián)系人或是會員按姓名為關(guān)鍵字排序,因?yàn)镹SArray并不直接支持對漢字的排序,這就要通過將漢字轉(zhuǎn)換成拼音完成按A~Z的排序,這看起來是個頭疼的問題,因?yàn)闋砍兜綕h字轉(zhuǎn)為拼音,獲取漢字的首字的首字母,如將“王”變成“W”。
函數(shù)原理是:我們知道,在Objective C語言中,字符串是以unicode進(jìn)行編碼的。在unicode字符集中,漢字的編碼范圍為4E00 到 9FA5 之間(即從第19968開始的20902個字符是中文簡體字符)。我們把這些字符的拼音首字母按照順序都存放在一個char數(shù)組中。當(dāng)我們查找一個漢字的拼音首字母時,只需把這個漢字的unicode碼(即char強(qiáng)制轉(zhuǎn)換為int)減去19968,然后用這個數(shù)字作為索引去找char數(shù)組中存放的字母即可。
給出項目的源碼,注釋很清楚。代碼如:
RYAddressBook.h
#import <Foundation/Foundation.h> #import "RYPersonInfo.h" typedef void (^AddressBookBlock) (NSArray *personInfos); @interface RYAddressBook : NSObject /** * 將數(shù)字轉(zhuǎn)化為字母 0~26 1~25=a~z 26=# */ NSString* SpellFromIndex(int index); /** * 獲取索引 */ int Index(NSString *firstSpell); /** * 獲取用戶所有通訊錄信息 * * @return 所有通訊錄數(shù)據(jù)信息數(shù)組 */ + (void)getPersonInfo:(AddressBookBlock)addressBookBlock; /** * 根據(jù)關(guān)鍵字匹配所有用戶信息 * * @param keyWord 匹配關(guān)鍵字 * * @return 匹配到的通訊錄數(shù)據(jù)信息數(shù)組 */ + (void)searchPersonInfo:(NSString *)keyWord addressBookBlock:(AddressBookBlock)addressBookBlock; /** * 根據(jù)姓名進(jìn)行數(shù)組的重排序 * * @param personInfos 獲取的通訊錄數(shù)據(jù)信息數(shù)組 */ + (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];
}
/**
* 根據(jù)關(guān)鍵字匹配所有用戶信息
*/
+ (void)searchPersonInfo:(NSString *)keyWord addressBookBlock:(AddressBookBlock)addressBookBlock
{
[[self alloc] searchPersonInfo:keyWord addressBookBlock:addressBookBlock];
}
/**
* 根據(jù)姓名進(jìn)行數(shù)組的重排序
*/
+ (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;
}
/**
* 根據(jù)關(guān)鍵字查詢通訊錄信息
*/
- (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
{
//如果沒有授權(quán)則退出
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);
}
// 類型轉(zhuǎn)換
blockArray = transformElements(blockArray);
// 返回BlockArray
self.addressBookBlock(blockArray);
}
/**
* 將所有元素轉(zhuǎn)化為JXPersonInfo類型數(shù)組
*/
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) // 姓_音標(biāo) PROPERTY_STR_READONLY(firstnamePhonetic) // 名_音標(biāo) PROPERTY_STR_READONLY(lastnamePhonetic) // 中間名_音標(biāo) PROPERTY_STR_READONLY(middlenamePhonetic) // 公司 PROPERTY_STR_READONLY(organization) // 工作 PROPERTY_STR_READONLY(jobtitle) // 部門 PROPERTY_STR_READONLY(department) // 生日 PROPERTY_STR_READONLY(birthday) // 備忘錄 PROPERTY_STR_READONLY(note) // 第一次創(chuàng)建用戶信息的時間 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 聯(lián)系人屬性 * * @return 實(shí)例對象 */ - (id)initWithABRecordRef:(ABRecordRef)ref; /** * 初始化類方法 * * @param ref 聯(lián)系人屬性 * * @return 實(shí)例對象 */ + (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
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
iOS實(shí)現(xiàn)底部彈出PopupWindow效果 iOS改變背景透明效果
這篇文章主要為大家詳細(xì)介紹了iOS實(shí)現(xiàn)底部彈出PopupWindow效果,iOS改變背景透明效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07
詳解iOS App開發(fā)中session和coockie的用戶數(shù)據(jù)存儲處理
iOS在HTTP網(wǎng)絡(luò)編程環(huán)境方面提供了NSURLSession、NSHTTPCookieStorage和NSHTTPCookie類來處理session和coockie的相關(guān)內(nèi)容,接下來我們將來詳解iOS App開發(fā)中session和coockie的用戶數(shù)據(jù)存儲處理:2016-06-06
iOS中containsString和rangeOfString的區(qū)別小結(jié)
這篇文章主要給大家總結(jié)介紹了關(guān)于iOS中containsString和rangeOfString的一些區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01
iOS runtime forwardInvocation詳解及整理
這篇文章主要介紹了 iOS runtime forwardInvocation詳解及整理的相關(guān)資料,需要的朋友可以參考下2017-02-02
iOS中實(shí)現(xiàn)動態(tài)區(qū)域裁剪圖片功能實(shí)例
圖片處理中經(jīng)常用的圖片剪裁,就是通過剪裁框確定圖片剪裁的區(qū)域,然后剪去該區(qū)域的圖片,下面這篇文章主要給大家介紹了關(guān)于iOS中實(shí)現(xiàn)動態(tài)區(qū)域裁剪圖片功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起看看吧。2017-11-11

