提取 NSString 的第一个 Unicode 代码点的最简单方法(在 BMP 之外)



由于历史原因,Cocoa的Unicode实现是16位的:它通过"代理对"处理0xFFFF以上的Unicode字符。这意味着以下代码将不起作用:

NSString myString = @"𠬠";
uint32_t codepoint = [myString characterAtIndex:0];
printf("%04xn", codepoint);  // incorrectly prints "d842"

现在,这段代码在 100% 的时间内有效,但它非常冗长:

NSString myString = @"𠬠";
uint32_t codepoint;
[@"𠬠" getBytes:&codepoint maxLength:4 usedLength:nil
    encoding:NSUTF32StringEncoding options:0
    range:NSMakeRange(0,2) remainingRange:nil];
printf("%04xn", codepoint);  // prints "20d20"

这个使用 mbtowc 的代码是有效的,但它仍然非常冗长,影响全局状态,不是线程安全的,并且可能会填满自动发布池:

setlocale(LC_CTYPE, "UTF-8");
wchar_t codepoint;
mbtowc(&codepoint, [@"𠬠" UTF8String], 16);
printf("%04xn", codepoint);  // prints "20d20"

是否有任何简单的Cocoa/Foundation习惯用法用于从NSString中提取第一个(或N个)Unicode代码点?最好是只返回代码点的单行代码?

在这个关于Cocoa Unicode支持的优秀总结(接近文章末尾)中给出的答案只是"不要尝试它。如果你的输入包含代理对,请过滤掉它们或其他东西,因为没有理智的方法可以正确处理它们。

单个 Unicode 代码点可能是代理项对,但并非所有语言字符都是单个代码点。 即并非所有语言字符都由一个或两个 UTF-16 单元表示。许多字符由一系列 Unicode 码位表示。

这意味着,除非你正在处理 Ascii,否则你必须将语言字符视为子字符串,而不是索引处的 unicode 代码点。

获取索引 0 处字符的子字符串:

NSRange r = [[myString rangeOfComposedCharacterSequenceAtIndex:0];
[myString substringWithRange:r];
这可能是你想要的,

也可能不是你想要的,这取决于你实际希望做什么。 例如,虽然这会给你"字符边界",但这些不会对应于特定于语言的光标插入点。

最新更新