美文网首页键盘上的鼓手iOS从入门到放弃GuaGua
简单实现iOS通讯录拼音分组排序

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

作者: 苹果防腐指南 | 来源:发表于2016-07-28 00:11 被阅读14897次

    在实现好友列表或通讯录功能时,我们大多需要对名字进行拼音排序及分组,后来在网上发现了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;
    }
    

    对于多音字的问题

    有小伙伴

    附:

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

    相关文章

      网友评论

      • _未可知:看了下,也对比了微信的的通讯录的排序方式,发现与题主有两点不同:一个是微信的排序是根据整个字符串去排序的,而不是根据首字母;一个是多音字的处理问题,微信应该是在所有的多音字中取最靠前的发音的字母,我在你的工程上小改了一下,但是希望题主可以出个官方的,可以添加不同的排序方式。
      • 苹果防腐指南:新版本有遇到问题的可以提issue,会及时跟进
      • winvsmary:RemoveSpecialCharacter没有起到过滤",.?、~¥#&<>《》()[]{}【】^@/£¤|§¨「」『』¢¬ ̄~@#&*()——+|《》$_€"这些特殊字符的作用
      • lemon007:厦门,会被分到,S,楼主解释下?
      • keepin:这个真心不错、
      • a396ddf1712f:请问一下,想把字母排序中的#放到排序的最下面要怎么操作?
      • xieyinghao:大神,请问怎么复制你代码过去,程序奔溃了,需要添加什么吗?
        报错信息:BMChineseSort user time in 32.714009 ms
      • _君莫笑_:同名怎么处理的?而且名字中有特殊字符不好使啊!
      • 云飞扬07:你好,我用于城市分类,但是"长沙"和"长春"怎么被分在了"Z"类?
        云飞扬07:@小怪兽_57fd 我就直接是把长沙和长春自己手动处理了一下, 其他多音字是没有处理的
        小怪兽_xxx:@云飞扬07 大神,求教,这个判断不起作用,有联系方式吗
        云飞扬07:查了一下,
        是CFStringTransform((__bridge CFMutableStringRef)pinyin, NULL, kCFStringTransformMandarinLatin, NO);
        方法将汉子转化为拼音错了.会将所有的长转化为zhang.

        自己在下面做了个判断:
        //如果首个汉字是"长",那么手动将拼音首字母转化为C
        if ([[chinese substringToIndex:1] isEqualToString:@"长"])
        {
        [result appendString:@"C"];
        continue;
        }
        但是不知道还有没有其他字会转换错:sweat:
      • zcz:楼主,给你赞一个:+1:
      • oceanfive:楼主,沈清这个名字怎么会被分到C里面的,这是多音字的问题,能不能处理下呀?
      • mf168:你这份代码 我见过一毛一样的 :disappointed_relieved:
      • 806349745123:有一个问题,如果我直接想对一个字符串数组排序,怎么用
        806349745123:@苹果防腐指南 感觉还是有点慢,我对全国所有地级市进行排序,300多个元素感觉有点慢
        806349745123:@苹果防腐指南 貌似没有,我在ReturnSortObjectArrar方法中对key参数进行空字符串判断就好了
        苹果防腐指南:@人类买水精华 你看了.h文件里的方法了吗 我记得我有直接给字符串排序的方法的呀
      • 苜蓿鬼仙:很感谢楼主,整好需要用到了!另外,在BMChineseSort.m 文件中的 +(NSMutableArray*)ReturnSortObjectArrar:(NSArray*)stringArr key:(NSString *)key 这个方法中,chineseString.string = [NSString stringWithString:[temp valueForKeyPath:key]]; 需要更改成 chineseString.string = [NSString stringWithString:[NSString stringWithFormat:@"%@", [temp valueForKeyPath:key]]]; 声明称字符串,不然的话有些时候会报错的
        苹果防腐指南:恩 没考虑到value的类型
      • 8d0b19aa64b3:这个查询效率即使是使用model2 在iPod上执行五百条的查询 需要耗时6.6s+800ms 完全不行 需要一个新的框架 本来项目中使用一个较老的框架 效率比这个高
        8d0b19aa64b3:@苹果防腐指南 老框架不行呢 我刚重写了个 耗时90ms 只使用首字母判断的话 我再加上全部长度的str试下 用的是字典的key value value内是index的数组
        苹果防腐指南:可以吧你的老框架发出来我研究下...我的还没加入多核的优化 应该还能再快的 话说你用的ipod?
      • 0df306bd4aa6:好的 那看你的
      • 0df306bd4aa6:我手动添加了,但是好像有根据用户习惯拼写的方法,我用了但是没成功。
      • 0df306bd4aa6:我用您的方法排序的时候,发现“重庆“会被排列到首字母为Z的行列中。。。

        苹果防腐指南:你不说我还没注意 应该是多音字的问题 这个没办法了 除非把词语传给服务器做词语识别拼音判断 不然就是唯一的了
        0df306bd4aa6:@苹果防腐指南 不是存错了,重 是多音字 会不会转过来的时候转错了?
        苹果防腐指南:@0df306bd4aa6 应该是那个首字母的数组里存的数据错了
      • jkpang:我有更好的实现方法,也很简单!
        简书地址 : http://www.jianshu.com/p/b51a6125bcff
        Github地址 : https://github.com/jkpang/PPGetAddressBook
        小道萧兮:这是来踢馆的吗?
      • 左手一只鸭:写的好工整啊 赞👍
        苹果防腐指南:@左手一只鸭 :joy:我一直觉得我写的很乱…
      • 晨曦之光nl:当姓名为“#”或者“?”等特殊字符时会崩溃在 NSString *pinyin = [str substringToIndex:1];这一句,原因是ReturnSortObjectArrar方法返回特殊字符时chineseString.pinYin = @"";导致crash,改成chineseString.pinYin = @"#";解决问题
        苹果防腐指南:嗯 多谢 晚上我看看
      • 丶大明:你好,请问怎么把#放在最后
        丶大明:@苹果防腐指南 恩,好~去试试 :blush:
        苹果防腐指南:@丶大明 把两个输出的数组的第一个元素扔到数组的末尾就可以了 先判断index的第一个是不是@“#” 这种方便一点:smile:
      • hhhhxy:系统有自带的东东,可以看看UILocalizedIndexedCollation
        苹果防腐指南:@iOS_hxy UILocalizedIndexedCollation只是提供了分组的算法 对于英文的排序很方便 但是没法直接给中文排序
      • 凯文Kevin21:厉害。。。。
        苹果防腐指南:@七秒小鱼人 看看源码很快就能明白原理 其实不难

      本文标题:简单实现iOS通讯录拼音分组排序

      本文链接:https://www.haomeiwen.com/subject/vnzojttx.html