用Unicode表情符dynamic创buildNSString
我有string@"Hi there! \U0001F603"
,它正确地显示喜欢你喜欢的表情符号Hi there! 😃
Hi there! 😃
如果我把它放在一个UILabel
。
但是我想像[NSString stringWithFormat:@"Hi there! \U0001F60%ld", (long)arc4random_uniform(10)]
那样dynamic地创build它,但是它甚至不能编译。 如果我加倍反斜杠,它显示的Unicode值真的像Hi there! \U0001F605
Hi there! \U0001F605
。
我怎样才能做到这一点?
退一步说:第一个数字是1F6603 16 ,它是一个Unicode 代码点 ,为了尽可能简单,它是所有Unicode项目列表中这个表情符号的索引。 这与计算机实际处理的字节不一样,它们是“编码值”(技术上,代码单元) 。
当你在你的代码中写入文字 @"\U0001F603"
时,编译器会为你编码,写入必要的字节。*如果你在编译时没有文字,你必须自己编码。 也就是说,您必须将代码点转换为一组代表它的字节。 例如,在NSString
内部使用的UTF-16编码中,您的代码点由字节ff fe 3d d8 03 de
。
在运行时,你不能修改这个文字,并以正确的字节结束,因为编译器已经完成了它的工作并上床睡觉。
(你可以在objc.io的Ole Begemann的文章中深入地读到这个东西,以及它如何与NSString
相关)
幸运的是,可用的编码之一UTF-32直接表示代码点:字节的值与代码点的值相同。 换句话说,如果您将您的代码点号码分配给一个32位无符号整数,那么您将得到正确的UTF-32编码数据。
这导致我们到你需要的过程:
// Encoded start point uint32_t base_point_UTF32 = 0x1F600; // Generate random point uint32_t offset = arc4random_uniform(10); uint32_t new_point = base_point_UTF32 + offset; // Read the four bytes into NSString, interpreted as UTF-32LE. // Intel machines and iOS on ARM are little endian; others byte swap/change // encoding as necessary. NSString * emoji = [[NSString alloc] initWithBytes:&new_point length:4 encoding:NSUTF32LittleEndianStringEncoding];
(注意,这可能无法按预期的方式工作,不是任何代码点都是有效的。)
*请注意,对于“普通”string(例如@"b"
)也是如此。
\U0001F603
是在编译时评估的文字。 你想要一个可以在运行时执行的解决scheme。
所以你想有一个dynamic的Unicodestring。 %C
如果Unicode字符( unichar
)的格式说明符。
[NSString stringWithFormat:@"Hi there! %C", (unichar)(0x01F600 + arc4random_uniform(10))];
表情符号太小了。 感谢@JoshCaswell纠正我。
更新:一个工作的答案
@JoshCaswell与-initWithBytes:length:encoding:
有正确的答案,但我想我可以写一个更好的包装。
- 创build一个function来完成所有的工作。
- 使用networkingsorting标准字节顺序。
- 没有幻数的长度。
这是我的答案
NSString *MyStringFromUnicodeCharacter(uint32_t character) { uint32_t bytes = htonl(character); // Convert the character to a known ordering return [[NSString alloc] initWithBytes:&bytes length:sizeof(uint32_t) encoding:NSUTF32StringEncoding]; }
所以,在使用…
NSString *emoji = MyStringFromUnicodeCharacter(0x01F600 + arc4random_uniform(10)); NSString *message = [NSString stringWithFormat:@"Hi there! %@", emoji];
更新2
最后,放入一个类别,使其成为真正的Objective-C。
@interface NSString (MyString) + (instancetype)stringWithUnicodeCharacter:(uint32_t)character; @end @implementation NSString (MyString) + (instancetype)stringWithUnicodeCharacter:(uint32_t)character { uint32_t bytes = htonl(character); // Convert the character to a known ordering return [[NSString alloc] initWithBytes:&bytes length:sizeof(uint32_t) encoding:NSUTF32StringEncoding]; } @end
再次,在使用中…
NSString *emoji = [NSString stringWithUnicodeCharacter:0x01F600 + arc4random_uniform(10)]; NSString *message = [NSString stringWithFormat:@"Hi there! %@", emoji];