亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

如何自定義iOS通訊錄

2020-07-26 03:07:15
字體:
來源:轉載
供稿:網友

蘋果給用戶提供了自己的通訊錄,但是根據業務的需求,需要自定義通訊錄,我們就需要根據業務需求來自定義。
首先我們需要知道蘋果的提供的一些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 

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人444kkkk在线观看| 2019中文在线观看| 在线成人一区二区| 丝袜美腿亚洲一区二区| 亚洲第一黄色网| 日韩精品免费在线视频| 91精品在线播放| 5566日本婷婷色中文字幕97| 国产激情999| 亚洲v日韩v综合v精品v| 奇米影视亚洲狠狠色| 91香蕉嫩草影院入口| 91亚洲精品久久久久久久久久久久| 欧美日韩激情美女| 伦理中文字幕亚洲| 亚洲精品自拍偷拍| 久久视频国产精品免费视频在线| 国产亚洲欧美日韩一区二区| 草民午夜欧美限制a级福利片| 国产精品海角社区在线观看| 亚洲国产精品成人av| 欧美日韩国产成人| 欧美精品少妇videofree| 91久久久久久久久久久| 亚洲美女精品成人在线视频| 2019精品视频| 亚洲人成电影网站色…| 日韩中文字幕欧美| 中文字幕亚洲综合久久| 欧美亚洲国产成人精品| 91av在线视频观看| 欧美在线观看视频| 中文字幕日韩欧美在线视频| 国产精品美女网站| 91欧美日韩一区| 久久天天躁日日躁| 精品视频在线观看日韩| 亚洲成色999久久网站| 久久精品小视频| 日韩av免费在线| 国产www精品| 日韩中文字幕在线看| 午夜精品一区二区三区视频免费看| 麻豆国产精品va在线观看不卡| 日韩日本欧美亚洲| 亚洲偷熟乱区亚洲香蕉av| 欧美日韩在线免费| 国产99视频在线观看| 国产精品嫩草影院久久久| 成人妇女免费播放久久久| 亚洲福利在线视频| 欧美日韩中文字幕日韩欧美| 欧美大片大片在线播放| 日韩精品在线播放| 日韩成人高清在线| 精品久久中文字幕| 91精品久久久久久久久久久| 国产精品丝袜白浆摸在线| 亚洲精品久久在线| 国产精品无码专区在线观看| 久久理论片午夜琪琪电影网| 久久久亚洲欧洲日产国码aⅴ| 中文字幕亚洲欧美日韩在线不卡| 国产精品成人播放| 日韩av免费在线播放| 亚洲综合第一页| 日韩a**中文字幕| 91在线中文字幕| 欧美性极品少妇精品网站| 精品国产电影一区| 国内精品美女av在线播放| 国产精品吹潮在线观看| 国产aaa精品| 欧美午夜激情视频| 亚洲午夜久久久影院| 韩国精品美女www爽爽爽视频| 亚洲国产精品人人爽夜夜爽| 欧美激情一区二区三区高清视频| 国精产品一区一区三区有限在线| 欧美日韩亚洲视频一区| 国产一区二区视频在线观看| 亚洲激情视频在线| 综合国产在线观看| 日韩国产高清污视频在线观看| 国内揄拍国内精品少妇国语| 欧美高清一级大片| 午夜精品久久久久久久99热浪潮| 亚洲美女视频网站| 日本最新高清不卡中文字幕| 亚洲一区二区三区四区在线播放| 欧美高清无遮挡| 日韩av男人的天堂| 啊v视频在线一区二区三区| 国产日韩精品在线播放| 亚洲国产日韩精品在线| 成人福利免费观看| 18性欧美xxxⅹ性满足| 亚洲欧洲av一区二区| 国产日韩在线观看av| 中文字幕少妇一区二区三区| 成人黄色免费在线观看| 精品久久久免费| 亚洲人成网站色ww在线| 在线观看精品自拍私拍| 精品呦交小u女在线| 青青在线视频一区二区三区| 久久久久久国产| 欧美成人全部免费| 亚洲欧美日韩精品久久| 亚洲视频999| 日韩av电影在线网| 日韩久久午夜影院| 国产精品日韩在线观看| 欧美在线视频网| 在线观看日韩欧美| 日韩在线一区二区三区免费视频| 欧美日韩亚洲视频一区| 91日本在线视频| 亚洲精品一区二区三区不| 欧美激情亚洲国产| 国产视频自拍一区| 亚洲欧美国产高清va在线播| 95av在线视频| 久久99久久久久久久噜噜| 亚洲精品中文字幕女同| 色多多国产成人永久免费网站| 国产有码一区二区| 成人久久18免费网站图片| 国产性猛交xxxx免费看久久| 久久久久在线观看| 91亚洲精品久久久| 激情av一区二区| 欧美与黑人午夜性猛交久久久| 国产97色在线|日韩| 国产在线视频2019最新视频| 欧美激情成人在线视频| 成人免费xxxxx在线观看| 高清欧美性猛交| 成人精品视频99在线观看免费| 中日韩美女免费视频网站在线观看| 欧美成人剧情片在线观看| 亚洲欧美制服丝袜| 伊人成人开心激情综合网| 欧美风情在线观看| 欧美特级www| 国产精品高潮呻吟视频| 91精品久久久久久久久久久久久| 亚洲欧洲日产国码av系列天堂| 久久精品99久久久香蕉| 国产精品盗摄久久久| 亚洲人成电影网站色…| 在线视频中文亚洲| 国产精品视频久久| 亚洲女人天堂视频| 午夜精品一区二区三区在线| 国产精品第2页| 亚洲国产成人精品女人久久久| 亚洲欧美一区二区三区情侣bbw| 国产综合香蕉五月婷在线| 在线免费观看羞羞视频一区二区| 精品国产一区二区三区久久久| 91免费精品国偷自产在线| 中文字幕久精品免费视频| 亚洲天堂av女优|