tableview中index对英文字符汉字字符(窄字符宽字符)处理

【问题描述】

开发iOS通讯录项目,遇到一个tableview 索引的问题。

测试同学发现一个bug:添加一个名字为宽字符A不能归并到索引A的section中,而是使用了添加了一个叫A的索引,如图:

上图中:右侧索引尾部发生异常。ABX并没有归并到正常的索引中,而是出现在正常索引的Z和#之间了。

【问题分析】

想了一下,应该是宽字符A和A的编码不一致导致的。

之前代码是这样的,看第二行使用正则表达式判断首字母是不是拉丁字母开头,然后标注此人是以某个字符开头的,代码如下:

    NSPredicate* HanziPred   = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",@"[\u4e00-\u9fa5]"];
    NSPredicate *EnglishPred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",@"^[A-Z].*$"];
    NSPredicate *numberPred  = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",@"^[0-9].*$"];
if([EnglishPred evaluateWithObject: first]){//拉丁字母
        self.firstLetter = self.latinString.length >0?[self.latinString substringToIndex:1]:@"#";
    }

通过正则表达式,将first赋值给firstLetter。正则表达式果然很强大,竟然可以兼容宽字符和窄字符。这样导致A和A都符合正则,但是确是两个不同的字符。

【解决办法】

我的解决办法是,事先创建一个静态全局字典,并初始化,在使用正则的时候,首先判断是否能从字典中匹配到宽字符,如果可以强制替换为窄字符。

static  NSDictionary* widthLetter;
-(id)init{
    self = [super init];
    self.firstLetter = @"#";
    widthLetter =  @{@"A":@"A"
                      ,@"B":@"B"
                      ,@"C":@"C"
                      ,@"D":@"D"
                      ,@"E":@"E"
                      ,@"F":@"F"
                      ,@"G":@"G"
                      ,@"H":@"H"
                      ,@"I":@"I"
                      ,@"J":@"J"
                      ,@"K":@"K"
                      ,@"L":@"L"
                      ,@"M":@"M"
                      ,@"N":@"N"
                      ,@"O":@"O"
                      ,@"P":@"P"
                      ,@"Q":@"Q"
                      ,@"R":@"R"
                      ,@"S":@"S"
                      ,@"T":@"T"
                      ,@"U":@"U"
                      ,@"V":@"V"
                      ,@"W":@"W"
                      ,@"X":@"X"
                      ,@"Y":@"Y"
                      ,@"Z":@"Z"};
    return self;
}

if([EnglishPred evaluateWithObject: first]){//拉丁字母
        //兼容宽字符
        if (widthLetter[first]) {
            self.firstLetter = self.latinString.length >0?widthLetter[first]:@"#";
        }else{
            self.firstLetter = self.latinString.length >0?first:@"#";
        }
    }

【结果】

A和A都能进入到A的索引中,如图:

时间: 2024-10-20 15:45:21

tableview中index对英文字符汉字字符(窄字符宽字符)处理的相关文章

VC++/MFC中WCHAR *转化为char *的方法,即宽字符和普通字符互相转化【已解决】

1.wchar *转 char * char *wtoc(wchar_t *wText) { DWORD dwNum = WideCharToMultiByte(CP_ACP, NULL, wText, -1,NULL, 0, NULL, FALSE);//把第五个参数设成NULL的到宽字符串的长度包括结尾符 char *psText = NULL; psText = new char[dwNum]; if(!psText) { delete []psText; psText = NULL; }

宽字符

1.宽字符是为了解决国际化,英文软件写好后,要发行到不同的国家,这时就需要使用宽字符,宽字符能把汉字当成一个字符. 2.字符集 <1>多字节字符集  (窄字符) <2>Unicode字符集(用来解决国际化)(宽字符) 3.MessageBox    MessageBox引用了windows.h文件. 宽字符与窄字符的区别:窄字符1字节,窄字符2字节. MessageBox这个函数与 设置有关,默认是unicode,这个设置应该只影响MessageBox函数吧. 宽字符有一个宏指令 

彻底弄懂UTF-8、Unicode、宽字符、locale

目录 Unicode.UCS UTF8 结论: 宽字符类型wchar_t locale 为什么需要宽字符类型 多字节字符串和宽字符串相互转换 最近使用到了wchar_t类型,所以准备详细探究下,没想到水还挺深,网上的资料大多都是复制粘贴,只有个结论,也没个验证过程.本文记录探究的过程及结论,如有不对请指正. Unicode.UCS UCS(Universal Character Set)本质上就是一个字符集. Unicode的开发结合了国际标准化组织所制定的?ISO/IEC 10646,即通用字

boost.log(八)宽字符记录

宽字符记录 Boost.Log支持包含本地字符集字符串的日志记录.基本上有两种方式做这件事.在 UNIX 系统上通常使用一些多字节字符编码 (例如 UTF-8) 用来表示本地字符.在这种情况下,Boost.Log库可以直接以纯 ASCII 的方式记录而不需要其它额外的设置. 在Windows 上常见的做法是使用宽字符串来表示本地字符串.此外大多数系统 API 也是使用的宽字符,这需要特定于 Windows 的接收器也支持宽字符.另一方面,通用的接收器,例如 TextFile,是面向字节的,你写入

[转] C++宽字符操作函数

字符分类: 宽字符函数         普通C            函数描述 iswalnum()      isalnum()       测试字符是否为数字或字母 iswalpha()       isalpha()        测试字符是否是字母 iswcntrl()         iscntrl()         测试字符是否是控制符 iswdigit()         isdigit()         测试字符是否为数字 iswgraph()      isgraph() 

Java学习(4):统计一个文件中的英文,中文,数字,其他字符以及字符总数

要求:统计一个文件中的英文,中文,数字,其他字符以及字符总数(此随笔以txt文件为例) import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; /** * 将一个文件中英文,中文,数字,其

Javascript --扩展String实现替换字符串中index处字符

String.prototype.replaceCharAt = function(n,c){ return this.substr(0, n)+ c + this.substr(n+1,this.length-1-n); } Javascript --扩展String实现替换字符串中index处字符

截字符串(汉字一个算两个字符,英文算一个字符)

------摘自动易(RSSFeed.asp) '************************************************** '函数名:GetSubStr '作  用:截字符串,汉字一个算两个字符,英文算一个字符 '参  数:str   ----原字符串 '        strlen ----截取长度 '返回值:截取后的字符串 '************************************************** Function GetSubStr(

字符在内存中最终的表示形式是什么?是某种字符编码还是码位(Code Point)?

字符在内存中最终的表示形式是什么?是某种字符编码还是码位(Code Point)? 根据我的了解,编码中有三个核心概念:1. 字符集(Character Set),可以说是一个抽象概念,字符的合集2. 码位(Code Point),将抽象的字符集中每一个字符映射到一个整数3. 字符编码(Encoding),按照某种编码规则用二进制来表示一个字符 我对码位这个概念理解的不是很清楚,Code point中说: The notion of a code point is used for abstra