【问题标题】:How to convert surrogate pair to Unicode scalar in Swift如何在 Swift 中将代理对转换为 Unicode 标量
【发布时间】:2015-09-25 18:34:10
【问题描述】:

以下示例取自Strings and Characters documentation

55357(十六进制的U+D83D)和56374(十六进制的U+DC36)是构成Unicode标量U+1F436的代理对,即DOG FACE字符。有没有办法去另一个方向?也就是说,我可以将代理对转换为标量吗?

我试过了

let myChar: Character = "\u{D83D}\u{DC36}"

但我收到“无效的 Unicode 标量”错误。

This Objective C answerthis project 似乎是自定义解决方案,但是 Swift(尤其是 Swift 2.0+)中是否有任何内置功能可以做到这一点?

【问题讨论】:

  • 直接指定码位:\u{1F436}。您链接到let sparklingHeart = "\u{1F496}" // ????, Unicode scalar U+1F496 的文档中有一个示例
  • 如果我不知道完整的代码点怎么办?也就是说,如果我只知道代理对呢?
  • String 有一个 init?(_ utf16: String.UTF16View) 方法,但我还没有找到如何从给定数组创建 String.UTF16View。 – 一个类似的问题(可能的解决方案)在这里:Is there a way to create a String from utf16 array in swift?.
  • @MartinR 很抱歉,您已经给出了 utf16 解码答案。虽然您可能还会发现 2.0 版本很有趣。
  • @AirspeedVelocity:stackoverflow.com/a/24757284/1187415 的代码也适用于 Swift 2。它有点长,因为它区分“输入结束”和“错误”条件。

标签: ios swift unicode scalar surrogate-pairs


【解决方案1】:

有一些公式可以根据代理对计算原始代码点,反之亦然。来自https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae

Section 3.7 of The Unicode Standard 3.0 定义了与代理对相互转换的算法。

大于0xFFFF 的代码点C 对应于代理对 <H, L> 按照以下公式:

H = Math.floor((C - 0x10000) / 0x400) + 0xD800
L = (C - 0x10000) % 0x400 + 0xDC00

反向映射,即从代理对 <H, L> 到 Unicode 代码点C,由以下给出:

C = (H - 0xD800) * 0x400 + L - 0xDC00 + 0x10000

【讨论】:

    【解决方案2】:

    给定一个 UTF-16 代码单元序列(即 16 位数字,例如从 String.utf16 或只是一个数字数组),您可以使用 UTF16 类型及其 decode 方法将其转换为UnicodeScalars,然后您可以将其转换为String

    这是一个有点蹩脚的项目,它接受一个生成器(因为它进行有状态处理)并返回一个枚举,该枚举指示一个结果(具有相关的标量类型),或者一个错误或完成。 Swift 2.0 模式匹配使它更易于使用:

    let u16data: [UInt16] = [0xD83D,0xDC36]
    //or let u16data = "Hello, ?".utf16
    
    var g = u16data.generate()
    var s: String = ""
    var utf16 = UTF16()
    while case let .Result(scalar) = utf16.decode(&g) {
        print(scalar, &s)
    }
    print(s) // prints ?
    

    【讨论】:

    • 我花了一些时间来学习一些新概念(1.decode method,2.生成器(herehere),3.stateful),但是这个是一个有用的答案。我想我最初的问题的答案是否定的,Swift 没有内置任何东西可以直接执行此操作,但生成起来并不难。
    猜你喜欢
    • 2016-10-22
    • 2016-12-11
    • 2019-03-06
    • 2020-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多