在實現(xiàn)好友列表或通訊錄功能時窄刘,我們大多需要對名字進行拼音排序及分組蔗怠,后來在網(wǎng)上發(fā)現(xiàn)了YUChineseSorting已經(jīng)實現(xiàn)了基本的字符串排序算法。但是它只能對字符串數(shù)組進行分組排序,并且還需要加入.cpp文件族购,使用比較麻煩攒盈。于是我在原來基礎(chǔ)上對代碼進行封裝抵拘,支持了對對象數(shù)組按對象的某個屬性進行排序。并對原來的代碼進行了合并和封裝型豁,比原來使用更方便僵蛛。
原理
在Objective C語言中,字符串是以unicode進行編碼的迎变。在unicode字符集中充尉,漢字的編碼范圍為4E00(16進制) 到 9FA5(16進制) 之間(即從第19968開始的20902個字符是中文簡體字符)。YUChineseSorting把這些字符的拼音首字母按照原來的順序都存放在一個char數(shù)組中衣形。當我們查找一個漢字的拼音首字母時驼侠,只需把這個漢字的unicode碼(即char強制轉(zhuǎn)換為int)減去19968姿鸿,然后用這個數(shù)字作為索引去找char數(shù)組中存放的字母即可。比較野蠻的一個方法倒源。
調(diào)用方法介紹
首先吧BMChineseSort.h及.m文件導(dǎo)入到項目中苛预,只需要這兩文件。
對自定義對象數(shù)組排序需要只需要使用兩類個方法:
+(NSMutableArray*)IndexWithArray:(NSArray*)objectArray Key:(NSString *)key;
+(NSMutableArray*)sortObjectArray:(NSArray*)objectArray Key:(NSString *)key;
第一個方法:一個參數(shù)objectArray是自定義對象數(shù)組笋熬,另一個參數(shù)key是數(shù)組里需要排序的字段名字热某。方法返回所有出現(xiàn)過的首字母,用于顯示在tableview的head以及右側(cè)索引縮寫胳螟。
獲得的兩個數(shù)組在tableview代理方法中的具體使用可以參考我的demo蔬捷,已上傳到github垄提。
具體tableView設(shè)置
Person對象:
@interface Person : NSObject
@property (strong , nonatomic) NSString * name;
@property (assign , nonatomic) NSInteger number;
@end
通訊錄控制器viewDidLoad方法:
// array是NSArray< Person *>類型的模擬數(shù)據(jù)
self.indexArray = [BMChineseSort IndexWithArray:array Key:@"name"];
self.letterResultArr = [BMChineseSort sortObjectArray:array Key:@"name"];
TableView代理方法:
//section的titleHeader
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [self.indexArray objectAtIndex:section];
}
//section行數(shù)
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return [self.indexArray count];
}
//每組section個數(shù)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [[self.letterResultArr objectAtIndex:section] count];
}
//section右側(cè)index數(shù)組
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{
return self.indexArray;
}
//點擊右側(cè)索引表項時調(diào)用 索引與section的對應(yīng)關(guān)系
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index{
return index;
}
//返回cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL"];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CELL"];
}
//獲得對應(yīng)的Person對象
Person *p = [[self.letterResultArr objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
cell.textLabel.text = p.name;
return cell;
}
# 2018.8.3更新v0.2.0
看到還有新同學再用我的庫,所以在看到兩年前的代碼那么丑的情況下周拐,對庫升級維護了下铡俐,整體速度快了1倍以上,具體更改如下:
1.合并
IndexWithArray:
和sortObjectArray:
方法妥粟,減少對數(shù)據(jù)的重復(fù)遍歷及轉(zhuǎn)拼音操作導(dǎo)致的時間浪費审丘,新方法為sortWithArray: key: finish:
2.將所有操作放入后臺線程,防止大數(shù)據(jù)時主線程阻塞勾给,通過block回調(diào)拿到數(shù)據(jù)滩报。
3.由于CFStringTransform屬于費時操作,所以在1000條數(shù)據(jù)實驗各種遍歷方法后播急,使用enumerateObjectsWithOptions方法進行多線程遍歷脓钾,進一步降低時間損耗
4.使用
BMChineseSortSetting
類在外部進行設(shè)置,不需像原來需要修改宏定義桩警,排除一些隱患-
4.對于多音字的想了個折中的辦法可训,由于本地判斷無法徹底解決多音字問題,所以在
BMChineseSortSetting
中通過polyphoneMapping
可以手動設(shè)置拼音映射關(guān)系捶枢,現(xiàn)在對于有和預(yù)期不符的拼音可以手動修改啦握截。BMChineseSortSetting.share.polyphoneMapping = @{@"重慶":@"CQ"};//單獨對重慶進行映射 BMChineseSortSetting.share.polyphoneMapping = @{@"長":@"C"};//所有長映射為chang(C)
5.將模型排序與字符串排序合并為一個方法,使接口更簡潔烂叔,如果是字符串數(shù)組谨胞,key傳nil即可
新接口使用方法:(具體查看demo)
[BMChineseSort sortWithArray:array key:@"name" finish:^(bool isSuccess, NSMutableArray<NSString *> *sectionTitleArr, NSMutableArray<NSMutableArray *> *sortedObjArr) {
if (isSuccess) {
// tableview reload
}
}];