美文网首页iOS开发ios开发约束问题程序员
获取iOS通讯录爬过的坑:联系人排序

获取iOS通讯录爬过的坑:联系人排序

作者: jkpang | 来源:发表于2016-08-23 15:39 被阅读3491次
效果图

PPGetAddressBook OC版

PPGetAddressBookSwift Swift版

前言

在之前的项目中要获取到手机系统的通讯录,并按联系人姓名的首字母拼音进行分组排序。弄到最后是分好组了,也排好序了,但有一个问题,就是A-Z的顺序是对的,但每组里面的联系人的顺序却是乱的,因为分组内的联系人没有对姓名的剩余的字进行排序。
  那问题来了,在取联系人首字拼音的时候就遍历了每个联系人,这里还要对剩余的汉字做拼音排序处理,各种遍历、循环、判断,到最后自己不仅搞得要疯掉,代码的运行效率还特别低。。。废话不多说,上代码!

代码

// 重新对所有大写字母Key值里面对应的的联系人数组进行排序
    //1.遍历联系人字典中所有的元素
    //利用到多核cpu的优势:参考:http://blog.sunnyxx.com/2014/04/30/ios_iterator/
    [addressBookDict enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id  _Nonnull key, NSMutableArray * _Nonnull keyPeopleArray, BOOL * _Nonnull stop) {
        //2.对每个Key值对应的数组里的元素来排序
        [keyPeopleArray sortUsingComparator:^NSComparisonResult(PPPersonModel*  _Nonnull obj1, PPPersonModel  *_Nonnull obj2) {
            
            return [obj1.name localizedCompare:obj2.name];
        }];

    }];
    
    // 将addressBookDict字典中的所有Key值进行排序: A~Z
    NSArray *peopleNameKey = [[addressBookDict allKeys] sortedArrayUsingSelector:@selector(compare:)];

其中addressBookDict是获取好的联系人字典,每一个大写字母Key(A~Z)都对应一个装着联系人模型(PPPersonModel)数组。先通过enumerateKeysAndObjectsWithOptions:遍历addressBookDict,然后在通过sortUsingComparator:对每组的联系人进行排序,这样就通过一次遍历循环就达到了排序的目的,又快又好。
  我已经对获取通讯录联系人做了封装,一句代码就可以获取经过已经排序好的联系人、原始排序的联系人,使用非常方便。代码如下:

//获取按联系人姓名首字拼音A~Z排序(已经对姓名的第二个字做了处理)
    [PPGetAddressBook getOrderAddressBook:^(NSDictionary<NSString *,NSArray *> *addressBookDict, NSArray *peopleNameKey) {
        //addressBookDict:装着所有联系人的字典
        //peopleNameKey:联系人分组按拼音分组的Key值;
        //刷新 tableView       
        [self.tableView reloadData];
    } authorizationFailure:^{
        NSLog(@"请在iPhone的“设置-隐私-通讯录”选项中,允许PPAddressBook访问您的通讯录");
    }];
//获取没有经过排序的联系人模型
    [PPGetAddressBook getOriginalAddressBook:^(NSArray<PPPersonModel *> *addressBookArray) {
       //addressBookArray:原始顺序的联系人数组
       //刷新 tableView       
        [self.tableView reloadData];
    } authorizationFailure:^{
       NSLog(@"请在iPhone的“设置-隐私-通讯录”选项中,允许PPAddressBook访问您的通讯录");
    }];

此封装的特性

  • PPGetAddressBook对AddressBook框架(iOS9之前)和Contacts框架(iOS9之后)做了对应的封装处理;
  • 支持获取按联系人姓名首字拼音A~Z排序(重点:已处理姓名所有字符的排序问题,排序更准确!**);
  • 支持获取原始顺序的联系人,未分组,可自行处理.
  • 已对号码中的"+86","-","()",空号和联系人姓名空白做了处理,不会出现因为数据源NULL导致程序crash的问题.
  • 对姓"长","沈","厦","地","冲"多音字进行优化处理.
代码已经托管到GitHub,如果你有更好的做法,希望不吝赐教! 如果觉得好用还请Star一波哈,你的Star是我持续更新的动力!

OC版: https://github.com/jkpang/PPGetAddressBook
Swift版: https://github.com/jkpang/PPGetAddressBookSwift

相关文章

网友评论

  • snail小菜:拿到联系人有重复的
  • snail小菜:大神怎么有重复人啊
  • Flysss1219:我下载你的demo直接用模拟器运行出来为什么有的联系人会重复?有的是2个相同的人,有的就是正常?
    学习学习中:@Flysss1219 请问你解决了这个问题了吗?
    学习学习中:我刚刚下载的demo ,每组的第一个联系人也会重复
    Flysss1219:然后我在真机上跑了,排序后每个分区的第一个联系人都是显示2个cell,而且对于多音字会混乱比如“曾”,它会跑到C的分区,同时在Z的分区还有
  • EvanJq:组内好像没有排序?
  • 16f351940212:添加个搜索功能呢?
  • 3f58e786b546:这个可以一试
  • 1eec26d198fc:难道只能获取通讯录么?我的是一个好友排列啊
    jkpang:@小布布的任意门 :+1: :+1: :+1: 抽时间我会将PPGetAddressBook重构的,看到时候能不能对外开启一个排序的接口, 传一个模型数组进去,返回一个排好序的数据源出来
    1eec26d198fc:@jkpang 嗯嗯,已经在弄了
    jkpang:@小布布的任意门 排序的原理你可以参照源码中的方法
  • 嗨_我是大鑫啊:,怎么加一个搜索框,来搜索呢?
    16f351940212:你好这个你做出来了吗? 加搜索功能
  • Clarles:很赞
    jkpang:@Clarles :grin::grin::grin:
  • KevinLwg:如果一个联系人有多个号码,需要在tableview中用多个cell展示,如何实现呢?大神
    jkpang:@KevinLwg 你可以自定义一个cell,在cell 内,一个label填充一个号码,可以用循环来写。最后cell 根据label 的数量调整高度
    KevinLwg:@jkpang 额,不是要折叠的效果。如果有3个号码,就用3个cell展示就好了。
    jkpang:@KevinLwg 一个联系人的所有号码是放在了一个数组中,如果是多个cell的折叠效果,可以去cocoaChina上找。把号码数组填充进折叠cell中就行
  • 00d10f8a50de:能否用数据库缓存做一下呢,这样性能会更好,钉钉通讯录应该就是用数据库缓存做的
    jkpang:@五星红旗700 这种方式我也想过,但是考虑到: 如果手机通讯录有很多联系人,但是有的APP的主界面就是联系人列表,就可能来不及缓存本地,就要显示. 缓存联系人的方式我会在找到一个比较好的解决方法后再加上去的,非常感谢你的建议!
  • 33a02bf71691:对多音字姓氏好像没有做处理呢 ?
    jkpang:@重复昵称 最新版已经对多音字姓做处理了,详情见GitHub
  • ff1f6460d9e9:能不能把座机号码的用户过滤掉呢?
    jkpang:@牛瑶 这个可不能过滤哦!毕竟每个人的需求不相同, 如果你需要过滤,,建议你获取出来后再自行处理
  • 小橙圈:#pragma mark - 获取联系人姓名首字母(传入汉字字符串, 返回大写拼音首字母)
    + (NSString *)getFirstLetterFromString:(NSString *)aString
    {
    里面的
    NSString *firstString = [strPinYin substringToIndex:1];
    传入空字符串有数组越界
    jkpang:@lkmscott 这个问题我已经修复好了,已经更新到github与CocoaPods. 这是我昨天的改动造成,非常感谢你发现了这个问题
    jkpang:@lkmscott 你是用的最新版吗,可能是我昨天的改动造成的,我先去吃饭,等会就修复这个问题:smile:
    小橙圈:@lkmscott 这个是因为我通讯录里存了个wgq3545456@icloud.com的FaceTime联系人
  • MindTheGap:github issue 有bug :blush:
    jkpang:@MindTheGap 已经在GitHub上回复你的问题了哦!谢谢你的问题 :smile:

本文标题:获取iOS通讯录爬过的坑:联系人排序

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