如果文本包含表情符号,则范围为零(从swift开始)

如果文本包含表情符号,则范围为零(从swift开始),swift,Swift,文本“欢迎我的申请…”。。❣️" 在NSRange和范围测试期间没有意义。如果❣️ 包含,范围返回为nil,我想知道为什么 func testA() { let testStr = "Welcome my application..❣️" let range = NSRange(location: 0, length: testStr.count) let wrapRange = Range(range, in: testStr)

文本“欢迎我的申请…”。。❣️" 在
NSRange
范围测试期间没有意义。如果❣️ 包含,范围返回为
nil
,我想知道为什么

func testA() {
        let testStr = "Welcome my application..❣️"

        let range = NSRange(location: 0, length: testStr.count)
        let wrapRange = Range(range, in: testStr)

        let testStrB = "Welcome my application.."

        let rangeB = NSRange(location: 0, length: testStrB.count)
        let wrapRangeB = Range(rangeB, in: testStrB)

        print("wrapRange: \(wrapRange) wrapRangeB: \(wrapRangeB)")
}
结果:

wrapRange: nil wrapRangeB: Optional(Range(Swift.String.Index(_rawBits: 1)..<Swift.String.Index(_rawBits: 1572864)))
wrapRange:nil wrapRangeB:Optional(范围(Swift.String.Index(\u rawBits:1)…)❣️是一个“扩展的grapheme群集”,但有两个UTF-16代码单元:

print("❣️".count)       // 1
print("❣️".utf16.count) // 2
let wrapRange = Range(range, in: testStr)
print(wrapRange)  // nil
NSRange
统计UTF-16代码单位(即
NSString
中的“字符”),因此创建包含完整Swift字符串范围的
NSRange
的正确方法是

let range = NSRange(location: 0, length: testStr.utf16.count)
或更好(自Swift 4起):


说明:在您的代码中(此处简化)

创建描述单个UTF-16代码单元的
NSRange
。无法在
testStr
中将其转换为
范围,因为其第一个
字符
由两个UTF-16代码单元组成:

print("❣️".count)       // 1
print("❣️".utf16.count) // 2
let wrapRange = Range(range, in: testStr)
print(wrapRange)  // nil

我可能遗漏了一些东西,但OP创建的NSRange实际上并没有绑定到字符串。他只是获取字符串长度并使用该长度创建一个NSRange,不是吗?此外,Swift 5从UTF-16字符串表示转换为UTF-8。我发现这有助于OP,所以我遗漏了一些东西,但如果是,请您详细说明一下,好吗你不介意吗?@Free昵称:请参阅更新。这与字符串的内部表示无关。@MartinR Ugh…我不知何故完全忽略了创建了一个
NSRange
,然后将其转换为一个快速范围作为参数传入字符串。睡得更香了。非常感谢您的解释!