【问题标题】:Swift string indexing combines "\r\n" as one char instead of twoSwift 字符串索引将 "\r\n" 组合为一个字符而不是两个
【发布时间】:2023-03-03 18:20:01
【问题描述】:

我正在使用 Swift 4.2 处理包含 \r\n 的字符串。我遇到了 Swift 索引的一种奇怪行为,似乎 \r\n 将被 Swift 索引方法视为一个字符而不是两个字符。我写了一段代码来呈现这种行为:

var text = "ABC\r\n\r\nDEF"

func printChar(_ lower: Int, _ upper: Int) {
    let start = text.index(text.startIndex, offsetBy: lower)
    let end = text.index(text.startIndex, offsetBy: upper)
    print("\"" + text[start..<end] + "\"")
}

printChar(0, 1) // "A"
printChar(1, 2) // "B"
printChar(2, 3) // "C"
printChar(3, 4) // new line
printChar(4, 5) // new line (okay, what's going on here?)
printChar(5, 6) // "D"
printChar(6, 7) // "E"
printChar(7, 8) // "F"

打印结果为

"A"
"B"
"C"
"
"
"
"
"D"
"E"
"F"

知道为什么会这样吗?

【问题讨论】:

    标签: swift string swift4


    【解决方案1】:

    TLDR:\r\n 是一个字素簇,在 Swift 中被视为单个 Character,因为 Unicode。


    • Swift 将\r\n 视为一个Character

    • Objective-C NSString 将其视为两个字符(就length 的结果而言)。

    On the swift-users forum有人写道:

    – "\r\n" 是单个Character。这是正确的行为吗?

    – 是的,Character 对应一个 Unicode 字素簇,“\r\n”被认为是单个字素簇。

    随后的回复发布了指向 Unicode 文档的链接,请查看 this table,其中正式声明 CRLF 是一个字形集群。

    看看Apple documentation on Characters and Grapheme Clusters

    通常将字符串视为字符序列,但在处理 NSString 对象或一般的 Unicode 字符串时,在大多数情况下处理子字符串比处理单个字符更好。原因是用户认为文本中的字符在很多情况下可能由字符串中的多个字符表示。

    Strings and Characters 上的 Swift 文档也值得一读。

    这个overview from objc.io也很有趣。

    NSString 表示 UTF-16 编码的文本。长度、索引和范围都基于 UTF-16 代码单元。

    另一个例子是像??这样的表情符号。这个单个字符实际上是 %uD83D%uDC4D%uD83C%uDFFB,四个不同的 unicode 标量。但是如果你在一个字符串上调用count,你会(正确地)得到1

    如果您想查看标量,可以按如下方式迭代它们:

    for scalar in text.unicodeScalars {
        print("\(scalar.value) ", terminator: "")
    }
    

    "\r\n" 的哪一个会给你13 10

    In the Swift documentation 你会发现为什么NSString 不同:

    count 属性返回的字符数并不总是与包含相同字符的 NSString 的 length 属性相同。 NSString 的长度基于字符串的 UTF-16 表示中 16 位代码单元的数量,而不是字符串中 Unicode 扩展字形簇的数量。

    因此,这并不是 Swift 字符串索引的真正“奇怪”行为,而是 Unicode 如何处理这些字符以及 Swift 中的String 是如何设计的结果。 Swift 字符串索引通过 Character\r\n 是单个 Character

    【讨论】:

    • 解释得很好
    猜你喜欢
    • 1970-01-01
    • 2011-10-24
    • 2016-06-19
    • 1970-01-01
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    相关资源
    最近更新 更多