How to customize iOS Address Book

  • 2021-06-28 09:48:50
  • OfStack

Apple provides users with their own address lists, but if we need to customize them to suit our business needs, we need to customize them to suit our business needs.
First of all, we need to know some Foundation, UIKit frameworks provided by Apple and some of them. You can open your mobile phone to view the native address book provided by Apple, you can see:

1. Search box
2. Right Search Bar
3. Contact Grouping
4. Add contacts
5. Get a contact picture and contact information

According to the requirements, you can summarize some functions that you need to do in a custom address book, one large function can be divided into one small function, and then one implementation can be used to divide complex problems into small problem solving.

1. Custom Search Box
2. Get the first letter
3. Judgment of Rights
4. Sorting
5. Custom Search
6. Customize the contact interface (get an address book image considering multiple values)

Sort under Brief Answer Introduction:

In the IOS project, the contact or member of the address book is sorted by name keyword, because NSArray does not directly support the sorting of Chinese characters. It seems a headache to complete the sorting by A~Z by converting Chinese characters to Pinyin, because it involves converting Chinese characters to Pinyin to get the first letter of Chinese characters.If "King" becomes "W".

The function works by knowing that strings are encoded in Objective C.In the unicode character set, the encoding range of Chinese characters is between 4E00 and 9FA5 (that is, 20902 characters since 1968 are simplified Chinese characters).We put the initial phonetic letters of these characters in an char array in order.When we look for the initial phonetic letter of a Chinese character, we simply subtract 19968 from the unicode code of the Chinese character (that is, the char forced conversion to int) and use this number as an index to find the letters stored in the char array.
Give the source code of the project and the notes are clear.Codes such as:
RYAddressBook.h


#import <Foundation/Foundation.h> 
#import "RYPersonInfo.h" 
 
typedef void (^AddressBookBlock) (NSArray *personInfos); 
 
@interface RYAddressBook : NSObject 
 
/** 
 *  Converting Numbers to Letters  0~26 1~25=a~z 26=# 
 */ 
NSString* SpellFromIndex(int index); 
 
/** 
 *  Get Index  
 */ 
int Index(NSString *firstSpell); 
/** 
 *  Get all user address book information  
 * 
 * @return  Array of all address book data information  
 */ 
+ (void)getPersonInfo:(AddressBookBlock)addressBookBlock; 
 
/** 
 *  Match all user information by keyword  
 * 
 * @param keyWord  Match keywords  
 * 
 * @return  Matched Address Book Data Information Array  
 */ 
+ (void)searchPersonInfo:(NSString *)keyWord addressBookBlock:(AddressBookBlock)addressBookBlock; 
 
/** 
 *  Reordering arrays by name  
 * 
 * @param personInfos  Array of Address Book Data Information Obtained  
 */ 
+ (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]; 
} 
 
/** 
 *  Get all user address book information  
 */ 
+ (void)getPersonInfo:(AddressBookBlock)addressBookBlock 
{ 
 [[self alloc] getPersonInfo:addressBookBlock]; 
} 
 
/** 
 *  Match all user information by keyword  
 */ 
+ (void)searchPersonInfo:(NSString *)keyWord addressBookBlock:(AddressBookBlock)addressBookBlock 
{ 
 [[self alloc] searchPersonInfo:keyWord addressBookBlock:addressBookBlock]; 
} 
 
/** 
 *  Reordering arrays by name  
 */ 
+ (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; 
} 
 
/** 
 *  Query address book information based on keywords  
 */ 
- (void)searchPersonInfo:(NSString *)keyWord 
{ 
 CFErrorRef error = NULL; 
 ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error); 
 
 //  Start querying address book  
 ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { 
  
 if (granted) { 
  [self filterContentForSearchText:keyWord]; 
 } 
 }); 
} 
 
/** 
 *  Start matching address book information  
 */ 
- (void)filterContentForSearchText:(NSString*)searchText 
{ 
 // Exit if not authorized  
 if (ABAddressBookGetAuthorizationStatus() != kABAuthorizationStatusAuthorized) { 
 return; 
 } 
 
 NSArray *blockArray = [NSArray array]; 
 
 CFErrorRef error = NULL; 
 ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error); 
 
 if([searchText length]==0) 
 { 
 // Query all  
 blockArray = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); 
  
 } else { 
  
 // Conditional Query  
 CFStringRef cfSearchText = (CFStringRef)CFBridgingRetain(searchText); 
 blockArray = CFBridgingRelease(ABAddressBookCopyPeopleWithName(addressBook, cfSearchText)); 
  
 CFRelease(cfSearchText); 
 } 
 
 //  Type Conversion  
 blockArray = transformElements(blockArray); 
 
 //  Return BlockArray 
 self.addressBookBlock(blockArray); 
} 
 
/** 
 *  Convert all elements to JXPersonInfo Type Array  
 */ 
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) 
// 第1次创建用户信息的时间 
PROPERTY_STR_READONLY(firstknow) 
// 最后1次更改用户信息的时间 
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 
 
/** 
 *  Single Value Information  
 */ 
#define GET_PROPERTY_METHOD(property, property_key) \ 
- (NSString *)property {\ 
return (NSString *)CFBridgingRelease(ABRecordCopyValue(_recordRef, property_key));\ 
} 
 
/** 
 *  Multivalue Information  
 */ 
#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 
/** 
 *  full name  
 */ 
- (NSString *)fullName 
{ 
 return [NSString stringWithFormat:@"%@%@%@", 
  nullStrToEmpty(self.lastName), 
  nullStrToEmpty(self.middlename), 
  nullStrToEmpty(self.firstName)]; 
} 
/** 
 *  Initials  
 */ 
- (NSString *)firstSpell 
{ 
 return getFirstSpell(self.fullName); 
} 
 
/** 
 *  Output model all information  
 */ 
- (NSString *)description 
{ 
 return [NSString stringWithFormat:@"%@ -- InfoPacket", 
  self.fullName]; 
} 
 
/** 
 *  Get First Letter  
 */ 
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 

Related articles: