简单实现iOS通讯录拼音分组排序

在实现好友列表或通讯录功能时,我们大多需要对名字进行拼音排序及分组,后来在网上发现了YUChineseSorting已经实现了基本的字符串排序算法。但是它只能对字符串数组进行分组排序,并且还需要加入.cpp文件,使用比较麻烦。于是我在原来基础上对代码进行封装,支持了对对象数组按对象的某个属性进行排序。并对原来的代码进行了合并和封装,比原来使用更方便。

原理

在Objective C语言中,字符串是以unicode进行编码的。在unicode字符集中,汉字的编码范围为4E00(16进制) 到 9FA5(16进制) 之间(即从第19968开始的20902个字符是中文简体字符)。YUChineseSorting把这些字符的拼音首字母按照原来的顺序都存放在一个char数组中。当我们查找一个汉字的拼音首字母时,只需把这个汉字的unicode码(即char强制转换为int)减去19968,然后用这个数字作为索引去找char数组中存放的字母即可。比较野蛮的一个方法。

调用方法介绍

首先吧BMChineseSort.h及.m文件导入到项目中,只需要这两文件。
对自定义对象数组排序需要只需要使用两类个方法:

+(NSMutableArray*)IndexWithArray:(NSArray*)objectArray Key:(NSString *)key;
+(NSMutableArray*)sortObjectArray:(NSArray*)objectArray Key:(NSString *)key;

第一个方法:一个参数objectArray是自定义对象数组,另一个参数key是数组里需要排序的字段名字。方法返回所有出现过的首字母,用于显示在tableview的head以及右侧索引缩写。

第二个方法:,是根据对象的某个字段值对整个数组进行排序,首先,先将字段首字母拼音相同的对象存到同一个数组里,然后把所有的数组再放到结果数组里。

获得的两个数组在tableview代理方法中的具体使用可以参考我的demo,已上传到github。

具体tableView设置

Person对象:
@interface Person : NSObject
@property (strong , nonatomic) NSString * name;
@property (assign , nonatomic) NSInteger number;
@end
通讯录控制器viewDidLoad方法:
// array是NSArray< Person *>类型的模拟数据
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行数
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return [self.indexArray count];
}
//每组section个数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [[self.letterResultArr objectAtIndex:section] count];
}
//section右侧index数组
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{
    return self.indexArray;
}
//点击右侧索引表项时调用 索引与section的对应关系
- (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"];
    }
    //获得对应的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:方法,减少对数据的重复遍历及转拼音操作导致的时间浪费,新方法为sortWithArray: key: finish:

  • 2.将所有操作放入后台线程,防止大数据时主线程阻塞,通过block回调拿到数据。

  • 3.由于CFStringTransform属于费时操作,所以在1000条数据实验各种遍历方法后,使用enumerateObjectsWithOptions方法进行多线程遍历,进一步降低时间损耗

  • 4.使用BMChineseSortSetting类在外部进行设置,不需像原来需要修改宏定义,排除一些隐患

  • 4.对于多音字的想了个折中的办法,由于本地判断无法彻底解决多音字问题,所以在BMChineseSortSetting中通过polyphoneMapping可以手动设置拼音映射关系,现在对于有和预期不符的拼音可以手动修改啦。

    BMChineseSortSetting.share.polyphoneMapping = @{@"重庆":@"CQ"};//单独对重庆进行映射
    BMChineseSortSetting.share.polyphoneMapping = @{@"长":@"C"};//所有长映射为chang(C)
    
  • 5.将模型排序与字符串排序合并为一个方法,使接口更简洁,如果是字符串数组,key传nil即可

新接口使用方法:(具体查看demo)

 [BMChineseSort sortWithArray:array key:@"name" finish:^(bool isSuccess, NSMutableArray *sectionTitleArr, NSMutableArray *sortedObjArr) {
        if (isSuccess) {
            // tableview reload 
        }
  }];
附:

BMChineseSort使用Demo
IOS数组按中文关键字以字母序排序

你可能感兴趣的:(简单实现iOS通讯录拼音分组排序)