iOS问题:Contacts框架排序联系人与原生顺序不一致
联系人排序与原生顺序不一致问题
我正在开发一个联系人展示页面,希望contactDictionary中的联系人顺序与设备原生联系人完全一致。我尝试使用Contacts框架提供的+ (NSComparator)comparatorForNameSortOrder:(CNContactSortOrder)sortOrder方法进行排序:
NSComparator comparator = [CNContact comparatorForNameSortOrder:CNContactSortOrderUserDefault]; NSArray<CNContact *> *sortedContacts = [listContacts sortedArrayUsingComparator:comparator];
但实际排序结果,和直接通过设置CNContactSortOrderUserDefault的CNContactFetchRequest获取到的联系人顺序并不一致。
获取原生顺序联系人的代码
CNContactFetchRequest *fetchRequest = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[ [CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName], CNContactPhoneNumbersKey, CNContactOrganizationNameKey, CNContactJobTitleKey, CNContactBirthdayKey, CNContactImageDataKey, CNContactThumbnailImageDataKey, CNContactImageDataAvailableKey, CNContactEmailAddressesKey, CNContactPostalAddressesKey, CNContactDatesKey, CNContactSocialProfilesKey, CNContactPhoneticGivenNameKey, CNContactPhoneticMiddleNameKey, CNContactPhoneticFamilyNameKey, CNContactNicknameKey ]]; CNContactSortOrder sortOder = CNContactSortOrderUserDefault; fetchRequest.sortOrder = sortOder; NSError *fetchError = nil; [contactStore enumerateContactsWithFetchRequest:fetchRequest error:&fetchError usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop){}];
两种排序结果对比
直接获取的原生联系人顺序
!Saz \Sa “Sa #Sa %Sa ‘Sa (Sa )Sa *Sa }Sa {Sa ,Sa -Sa A Sa .Sa /Sa :Sa Sa !!Sa !?Saz ;Sa ?Sa @Sa [Sa \Sa ]Sa ??Saz ]!Sa ![Sa !!Sa ]?Sa ?[Sa &?Saz Sa ! =Sa 123hange
使用comparatorForNameSortOrder排序后的顺序
-Sa ,Sa ;Sa :Sa Sa ! !!Sa !!Sa !?Saz ![Sa !Saz ??Saz ?[Sa ?Sa .Sa ‘Sa “Sa (Sa )Sa [Sa ]!Sa ]?Sa ]Sa {Sa }Sa @Sa *Sa /Sa \Sa \Sa &?Saz #Sa %Sa =Sa 123hange A Sa Sa
问题原因与解决方案
原因
CNContact的comparatorForNameSortOrder:方法仅针对联系人的姓名核心字段(如给定名、姓氏、拼音名等)进行排序,而系统原生联系人的排序逻辑更为复杂:
- 包含特殊符号前缀的Unicode排序权重规则
- 区分个人联系人和组织联系人的排序优先级
- 可能涉及昵称、自定义标签等其他字段的影响
CNContactFetchRequest的排序是系统底层完成的,覆盖了所有这些维度,单纯用公开的comparator无法完全复刻。
解决方案
优先方案:直接复用原生顺序
如果业务允许,在通过enumerateContactsWithFetchRequest:获取联系人时,直接将联系人按枚举顺序存入数组,避免后续二次排序,这是保证和原生顺序完全一致的最简单方法。备选方案:自定义Comparator(近似实现)
如果必须对已有联系人数组排序,需要自定义Comparator,模拟系统的排序逻辑:- 先处理特殊符号的Unicode排序权重(可参考系统的
NSStringCompareOptions中的Unicode编码相关规则) - 区分个人/组织联系人的排序优先级
- 结合姓名、拼音名、昵称等多字段综合排序
但注意:系统的排序逻辑并未完全公开,自定义实现很难做到100%一致,仅适合对一致性要求不极高的场景。
- 先处理特殊符号的Unicode排序权重(可参考系统的
内容的提问来源于stack exchange,提问作者Pxxx
相关产品推荐
相关产品推荐

