Unicode

    Unicode是一套国际通用的编码标准,用于在不同的系统中表示和处理文本数据。它让你可以用同一种形式表示几乎所有国家的所有语言,并且可对外部数据源进行读写操作,比如文本文件或者web页面。

    Swift的String和Character类型是完全兼容Unicode的,之前文章中也提过。

Unicode标量

    本质上,Swift中的String类型是通过Unicode标量创建的。一个Unicode标量是一个独一无二的21位的数字,代表了一个字符或者修饰符。比如U+0061表示了LATIN SMALL LETTER A的a,U+1F425表示FRONT-FACING BABY CHICK🐥。

    需要注意的是不是所有的21位的Unicode编码单元都被分配给了一个字符,有一些是保留到未来分配的。已经被分配给字符使用的标量一般都有一个名字,比如上述例子中的LATIN SMALL LETTER AFRONT-FACING BABY CHICK。

NOTE:一个Unicode标量是一个编码空间在[U+0000,U+D7FF] 或者[U+E000 ,U+10FFFF]中的任意编码单元。Unicode不包含代理对,也就是处于编码空间[U+D800, U+DFFF]中的编码单元。

可扩展的字形集群

    Swift中的每一个Character实例都表示了一个单独的可扩展的字形集群。一个可扩展的字形集群由一个或者多个Unicode标量组成,并可以生成人类可读的字符。

        let eAcute: Character = "\u{E9}" // é

        let combinedEAcute: Character = "\u{65}\u{301}"          // e followed by ́

        // eAcute is é, combinedEAcute is é

    上面是一个例子,字母é可以用单独的Unicode标量表示(LATIN SMALL LETTER E WITH ACUTE, or U+00E9),然而,字母é也可以用一对标量表示出来-----字母e(LATIN SMALL LETTER)后面跟随一个字母  ́(COMBINING ACUTE ACCENT) ,也就是U+0065跟随U+0301。在标量COMBINING ACUTE ACCENT被Unicode文本渲染系统渲染的时候,他会以图形化的方式作用于它前面的标量。把e变成é。

    上面的两个例子中,字母é都是用一个单独的Character值来表示出字形集群。第一个例子,集群包含了一个标量,第二个例子,包含了2个标量。

    可扩展的字符集群增加了灵活性,是我们可以使用一个单独的字符去表示很多复杂的脚本字符。比如,韩国字母中的音节可以表示成一组被预分解或者分解后的元素。下面两个字符在Swift中表示同一个字形:

        let precomposed: Character = "\u{D55C}" // 한

        let decomposed: Character = "\u{1112}\u{1161}\u{11AB}"  // ᄒ, ᅡ, ᆫ

        // precomposed is 한, decomposed is 한

    可扩展的字符集群使可以包围其他的标量,使其称为字符的一部分:

        let enclosedEAcute: Character = "\u{E9}\u{20DD}"

        // enclosedEAcute is é⃝     

地区指示符的Unicode标量可以被组合在一起,生成一个新的字符,比如把REGIONAL INDICATOR SYMBOL LETTER U (U+1F1FA)和 REGIONAL INDICATOR SYMBOL LETTER S (U+1F1F8)组合在一起:

        let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"

        // regionalIndicatorForUS is 🇺🇸

字符的数量

要获取String中character的数量,可以使用String的count属性:

        let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"

        print("unusualMenagerie has \(unusualMenagerie.count) characters")

        // 打印 "unusualMenagerie has 40 characters

值得注意的是,由于Swift中Character对可扩展自信集群的使用,使得字符串的连接或修改并不一定会改变字符串中字符的数量。

        var word = "cafe"

        print("the number of characters in \(word) is \(word.count)")

        // "the number of characters in cafe is 4"

        word += "\u{301}"    // COMBINING ACUTE ACCENT, U+0301

        print("the number of characters in \(word) is \(word.count)")

        // "the number of characters in café is 4

    例如,你先使用4个字符cafe初始化了一个新的字符串,然后在末尾拼接上字符COMBINING ACUTE ACCENT (U+0301),结果还是4个字符,因为第4个字符从e变成了é

NOTE:可扩展的字形群可以有多个Unicode标量组成,这就意味着不同的字符或者字符相同代表的结果却不同,需要存储的内存也不一样。因此,Swift中,字符串中的字符所占的内存不都是一样的。这就导致了如果不遍历字符串就无法确定字形群的边界,也就无法确定字符串中字符的数量。如果你正在处理特别长的字符串,注意count属性需要遍历整个字符串的Unicode标量以确定字符串的字符数量。

拥有相同字符的NSString的length和count返回的字符的数量不总是相同的。NSString的length是基于Utf-16的,也就是16位的代码单元,而不是String中可扩展字形群。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 在当前这个时代(比如说公元2016年),如果你并不是在维护历史遗留的文本处理代码,没有在每个地方都使用Unicod...
    纵横而乐阅读 2,775评论 3 16
  • 居然不能用整数下标随机访问? 第一次使用Swift字符串之前,已经习惯了C,C++直接通过下标随机访问字符串数组的...
    ameerkat阅读 5,737评论 1 4
  • Unicode®标准附录#9 UNICODE双向算法#### 摘要#### 本附件是一份关于字符定位的规范,主要描...
    Eriice阅读 4,884评论 0 6
  • 注:本翻译使用符号「」来突出某些可能会产生歧义的名词。目前状态:勘误中。 Unicode®标准附录#9 UNICO...
    Eriice阅读 2,141评论 0 1
  • 一天天的天气实在让人难以消受。 已经接近体温了。 盐城龙卷风的消息让人难过。 老家徐州离盐城不远。这次灾难遇难98...
    安星阅读 115评论 0 0