从变量中打印Unicode字符(Swift)

18

我有一个问题,我找不到解决方法。 我有一个字符串变量保存着 Unicode 编码 "1f44d",我想将它转换成一个 Unicode 字符。

通常情况下,人们会这样做:

println("\u{1f44d}") // 

这是我的意思:

let charAsString = "1f44d" // code in variable
println("\u{\(charAsString)}") // not working

我尝试了几种其他方法,但是这个魔法背后的工作方式总是对我隐藏着。

人们应该想象charAsString的价值来自于API调用或另一个对象。


1
七年过去了,苹果仍然没有修复这个问题。 - Sebastian
7个回答

13

一个可能的解决方案(内联解释):

let charAsString = "1f44d"

// Convert hex string to numeric value first:
var charCode : UInt32 = 0
let scanner = NSScanner(string: charAsString)
if scanner.scanHexInt(&charCode) {

    // Create string from Unicode code point:
    let str = String(UnicodeScalar(charCode))
    println(str) // 
} else {
    println("invalid input")
}

使用Swift 2稍微简单一些:

let charAsString = "1f44d"

// Convert hex string to numeric value first:
if let charCode = UInt32(charAsString, radix: 16) {
    // Create string from Unicode code point:
    let str = String(UnicodeScalar(charCode))
    print(str) // 
} else {
    print("invalid input")
}

还要注意,不是所有的代码点都是有效的 Unicode 标量,可以参考在 Swift 中验证 Unicode 代码点


Swift 3 更新:

public init?(_ v: UInt32)

现在,UnicodeScalar 的初始化器可以失败,并检查给定的数字输入是否是有效的 Unicode 标量值:

is now a failable initializer of UnicodeScalar and checks if the given numeric input is a valid Unicode scalar value:

let charAsString = "1f44d"

// Convert hex string to numeric value first:
if let charCode = UInt32(charAsString, radix: 16),
    let unicode = UnicodeScalar(charCode) {
    // Create string from Unicode code point:
    let str = String(unicode)
    print(str) // 
} else {
    print("invalid input")
}

重复使用其他用户的答案来改进您自己的答案在这里似乎是一种糟糕的方式...但我可能错了,也许这是一种常见的做法。 - Fantattitude
1
@Fantattitude:信不信由你,但在我编辑这个答案时,我并没有看到你的回答,而是使用了我自己之前回答中的代码https://dev59.com/9l4d5IYBdhLWcg3wFPM7#27190430。 - Martin R
我相信你不用担心,只是觉得有点严厉。我多年来一直只是阅读,现在开始参与,可能会犯错误。但你可以通过去掉基数(默认值似乎在这里运行良好)来改进你的答案。 - Fantattitude
1
@Fantattitude:不,它并没有,如果我尝试运行你的代码,它实际上会崩溃。 - Martin R
@MartinR 哦,好吧,Playground 愚弄了我,我删除后没有更新。 - Fantattitude
显示剩余4条评论

12

这可以分两步完成:

  1. charAsString转换为Int代码
  2. 将代码转换为Unicode字符

第二步可以像这样完成

var code = 0x1f44d
var scalar = UnicodeScalar(code)
var string = "\(scalar)"

首先,看一下这里如何将十六进制表示的String转换为Int


将十六进制字符串(如“1f44d”)转换为整数的简短代码: Int(strtoul(charAsString, nil, 16)) - yesman82
这对我很有效;我将变量转换为let,并在标量步骤上使用了一个守卫,以避免打印可选项。 - TahoeWolverine

7
从Swift 2.0开始,每个Int类型都有一个初始化程序可以将String作为输入。然后,您可以轻松生成相应的UnicodeScalar并在之后打印它。而不必更改字符作为字符串的表示方式 ;).
更新:Swift 3.0更改了UnicodeScalar初始化程序。
print("\u{1f44d}") // 

let charAsString = "1f44d" // code in variable

let charAsInt = Int(charAsString, radix: 16)! // As indicated by @MartinR radix is required, default won't do it
let uScalar = UnicodeScalar(charAsInt)! // In Swift 3.0 this initializer is failible so you'll need either force unwrap or optionnal unwrapping

print("\(uScalar)")

1
使用Swift 3.0。除非我也添加感叹号来让uScalar = UnicodeScalar(charAsInt)!,否则您的答案不会打印所需的结果,否则我看到的是Optional("\u{0001F44D}")。 - svohara

1
我制作了这个扩展程序,它运行得非常好:

extension String {
    var unicode: String? {
        if let charCode = UInt32(self, radix: 16),
           let unicode = UnicodeScalar(charCode) {
            let str = String(unicode)
            return str
        }
        return nil
    }
}

如何测试它:

if let test = "e9c8".unicode {
    print(test)
}

//打印:enter image description here


1
这里有几种方法可以做到:

let string = "1f44d"

解决方案1:
"&#x\(string);".applyingTransform(.toXMLHex, reverse: true)

解决方案2:
"U+\(string)".applyingTransform(StringTransform("Hex/Unicode"), reverse: true)

1
你可以使用

标签


let char = "-12"
print(char.unicodeScalars.map {$0.value }))

您将获得以下值:

[45, 49, 50]

0

你不能像尝试使用它一样在Swift中使用字符串插值。因此,以下代码将无法编译:

let charAsString = "1f44d"
print("\u{\(charAsString)}")

你需要将字符串变量转换为整数(使用init(_:radix:)初始化器),然后从该整数创建一个Unicode标量。下面是Swift 5 Playground示例代码,演示如何进行此操作:
let validCodeString = "1f44d"
let validUnicodeScalarValue = Int(validCodeString, radix: 16)!
let validUnicodeScalar = Unicode.Scalar(validUnicodeScalarValue)!
print(validUnicodeScalar) // 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接