实现通讯录分组排序的一个方法

在APP开发中,我们经常会去做一个通讯录。所有做iOS开发的都知道这玩意儿应该用UITableView来做。但是,如何将数据分组排序总是一个比较麻烦的问题,这里提供我个人的解决方法供大家参考。


排序的目标

因为要是用UITableView,所以我们的数据源应该是这样一个数组:数组dataArray拥有27个子数组subArray,前26个subArray存储以A到Z开头的联系人,第27个数组存储不以字母开头的联系人,也就是我们常见的#。另外我们需要一个titileArray数组用来作为数组右侧的索引和每个section的标题。
再次明确一下我们的目标:一个dataArray,包含27个subArray,另外需要一个titleArray。

获取首字母

如果我们的联系人都是英文名,这一步就很简单,但是有中文名怎么办呢? 没关系,OC其实给我们提供了一个方法用来将汉字转化成拼音,这样我们就能很方便的取到首字母了。
我们首先写下获取首字母的方法

- (NSString *)returnFirstWordWithString:(NSString *)str
{
NSMutableString * mutStr = [NSMutableString stringWithString:str];

 //将mutStr中的汉字转化为带音标的拼音(如果是汉字就转换,如果不是则保持原样)
CFStringTransform((__bridge CFMutableStringRef)mutStr, NULL, kCFStringTransformMandarinLatin, NO);
//将带有音标的拼音转换成不带音标的拼音(这一步是从上一步的基础上来的,所以这两句话一句也不能少)
CFStringTransform((__bridge CFMutableStringRef)mutStr, NULL, kCFStringTransformStripCombiningMarks, NO);
if (mutStr.length >0) {
     //全部转换为大写    取出首字母并返回
     NSString * res = [[mutStr uppercaseString] substringToIndex:1];
    return res;
}
else
    return @"";

}
按首字母分组排序

前面说过,我们的27分别代表从A到Z再加上#,那么我们这一步就是要将上一步获得的首字母所对应的联系人放到相应的数组中去(比如把 奔跑的炸鸡放到第二个数组,因为它代表B开头的联系人)。
那我们需要写27个if语句吗?
当然不是,我们有更简单的方法,但是我们需要先回忆两个小知识点

  1. 记得A到Z对应的ASCⅡ码吗?是65到90。在Unicode编码中,A到Z对应的也是65到90。
  1. 记得在C语言中,一个char类型其实就是一个字节的int类型吗?如果将char作为int去取值,那么A就是65,Z就是90。

通过以上两点我们就可以将拿到首字母的联系人直接放到对应的数组,无需任何比较

接下来是代码

- (void)dealDataWithArray:(NSArray *)array
{

NSMutableArray * tmpArray = [[NSMutableArray alloc]init];
for (NSInteger i =0; i <27; i++) {
    //给临时数组创建27个数组作为元素,用来存放A-Z和#开头的联系人
    NSMutableArray * array = [[NSMutableArray alloc]init];
    [tmpArray addObject:array];
}

for (AddressModel * model in array) {
     //AddressMode是联系人的数据模型
    //转化为首拼音并取首字母
    NSString * nickName = [FunctionModule returnFirstWordWithString:model.nickname];
    int firstWord = [nickName characterAtIndex:0];
    
    //把字典放到对应的数组中去
    
    if (firstWord >= 65 && firstWord <= 90) {
   //如果首字母是A-Z,直接放到对应数组
            NSMutableArray * array = tmpArray[firstWord - 65];
            [array addObject:model];
        
    }
    else
    { 
        //如果不是,就放到最后一个代表#的数组
        NSMutableArray * array =[tmpArray lastObject];
        [array addObject:model];
    }
}

//此时数据已按首字母排序并分组
//遍历数组,删掉空数组
for (NSMutableArray * mutArr in tmpArray) {
    //如果数组不为空就添加到数据源当中
    if (mutArr.count != 0) {
        [self.dataArray addObject:mutArr];
        AddressModel * model = mutArr[0];
        NSString * nickName = [FunctionModule returnFirstWordWithString:model.nickname];
        int firstWord = [nickName characterAtIndex:0];
        //取出其中的首字母放入到标题数组,暂时不考虑非A-Z的情况
        if (firstWord >= 65 && firstWord <= 90) {
            [self.titleArray addObject:nickName];
        }
    }
}
//便利结束后,两个数组数目不相等说明有除大写字母外的其他首字母
if (!(self.titleArray.count == self.dataArray.count)) {
    [self.titleArray addObject:@"#"];
}

//刷新tableView
[self.tableView reloadData];
}
效果展示
效果展示
一些不算坑的坑

1.右侧的索引列表,网上给出的答案是实现 - (NSArray *)titleArrayAtIndexes:(NSIndexSet *)indexes方法,但是实际上这个方法已经无效了,现在应该去实现
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return self.titleArray;
}

2.还是索引,默认的索引是文字是蓝色的,还会打一个白色的半透明图层,这两个东西其实是可以直接设置的。代码如下:

    //设置索引文字颜色
    self.tableView.sectionIndexColor = ColorFromRGB(0x646464);
    //设置索引背景颜色
    self.tableView.sectionIndexBackgroundColor = [UIColor clearColor];

3.section的那种悬浮效果,只有当tableView的风格是Plain的时候才会有。

4.tableView底部多余空白Cell可以通过设置TableViewFooter解决

self.tableView.tableFooterView = [UIView new];

结语

最近事情有点多,拖了很久才写。
这里只是提供个人使用的方法,如果有错误之处欢迎指出。
如果我的文章对您有帮助,请点赞或评论。
我们下篇文章见!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 首页 资讯 文章 资源 小组 相亲 登录 注册 首页 最新文章 IT 职场 前端 后端 移动端 数据库 运维 其他...
    Helen_Cat阅读 3,781评论 1 10
  • NumPy是Python中关于科学计算的一个类库,在这里简单介绍一下。 来源:https://docs.scipy...
    灰太狼_black阅读 1,202评论 0 4
  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,660评论 0 33
  • 1.落笔缘由 字符串在程序中使用得太频繁了,而java.lang.String中包含着许多有用的方法,但是由于平时...
    lgy_gg阅读 494评论 0 1
  • 在这个世界上有许许多多好看的植物,但我最喜欢的就是仙人掌。虽然它并不漂亮也带刺伤人,但是它的精神却闪闪发光吸引着我...
    你是明月啊阅读 2,599评论 1 11