我有字符串@"Hi there! \U0001F603"
,如果我将其放在Hi there!
中,它会正确显示UILabel
这样的表情符号。
但我想像[NSString stringWithFormat:@"Hi there! \U0001F60%ld", (long)arc4random_uniform(10)]
一样动态创建它,但它甚至不编译。
如果我将反斜杠加倍,它会显示Unicode值,就像Hi there! \U0001F605
。
我怎样才能做到这一点?
答案 0 :(得分:3)
\U0001F603
是一个在编译时计算的文字。您需要一个可以在运行时执行的解决方案。
所以你想要一个带有动态unicode字符的字符串。 %C
如果是unicode字符(unichar
)的格式说明符。
[NSString stringWithFormat:@"Hi there! %C", (unichar)(0x01F600 + arc4random_uniform(10))];
击> <击> 撞击>
对于表情符号来说, unichar
太小了。谢谢@JoshCaswell纠正我。
更新:工作答案
@JoshCaswell对-initWithBytes:length:encoding:
有正确答案,但我想我可以写一个更好的包装器。
这是我的回答
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];
答案 1 :(得分:2)
退一步,第二步:你拥有的那个号码,1F6603 16 ,是一个Unicode 代码点,试图把它简单地放在可能,是所有Unicode项列表中此表情符号的索引。这与计算机实际处理的字节不同,它们是&#34;编码的值&#34; (从技术上讲,代码单位。
当您在代码中编写 literal @"\U0001F603"
时,编译器会为您编写编码,编写必要的字节。*如果您在编译时没有文字时间,你必须自己做编码。也就是说,您必须将代码点转换为表示它的一组字节。例如,在NSString
内部使用的UTF-16编码中,您的代码点由字节ff fe 3d d8 03 de
表示。
你不能在运行时修改那个文字,最后得到正确的字节,因为编译器已经完成了它的工作并上床睡觉。
(您可以在an article by Ole Begemann at objc.io中深入了解这些内容及其与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];
(N.B。对于任意代码点,这可能无法正常工作;并非所有代码点都有效。)
*注意,它对#34;正常&#34;做同样的事情。像@"b"
这样的字符串。