これは、エスケープ シーケンス\Uxxxxxxxx
がコンパイラによって評価され、対応する Unicode コード ポイントに置き換えられるためです。次に、メソッドstringWithFormat:
がフォーマット指定子%i
を の 10 進数表現に置き換えるときi
。最後の文字列は、 に対応する\Uxxxxxxxx
文字と を表す文字を連結したものi
です。stringWithFormat:
文字を他の文字に置き換えます。既存の文字は変更されません。
しかし問題は、ここでコンパイラが不完全なエスケープ シーケンスを認識していることです。そのため、文字列を生成できず、エラーが発生します。
解決策は、実行時に文字 (単純な整数値) を生成し、それを使用して文字列を作成すること+[NSString stringWithCharacters:length]
です。
NSString
しかし、ヘッダーを調べると、がその文字を としてunichar
定義されている、つまり 16 ビット長の値として格納していることがわかりますがunsigned short
、Unicode コード ポイントU+1F430
() には少なくとも 17 ビットが必要です。
そのため、単一のunichar
文字を使用してそのコード ポイントを表すことはできません。しかし、心配する必要はありません。2 つの文字を使用して表すことができます。
迷った?解説はこちら!Unicode は文字を定義しません。範囲内の任意の整数値であるコード ポイントを定義しますU+0000
– U+10FFFF
. 次に、実装は、文字を使用してそれらのコード ポイントを表す方法を決定します。実装は、すべての有効なコード ポイントを表すことができる限り、必要な任意のデータ型を文字として使用できます。最も簡単な解決策は、32 ビット長の整数を使用することですが、使用するコード ポイントのほとんどが最初の Unicode プラン ( U+0000
– U+FFFF
) にあるため、大量のメモリが必要になります。そのため、 16 ビット長の文字を使用する UTF-16 エンコーディングNSString
でコード ポイントを格納します。
UTF-16 では、それ以降のすべてのコード ポイントはU+FFFF
、範囲内の文字のペア (サロゲート ペアと呼ばれます) を使用して格納されます(対応するコード ポイントは、Unicode 標準で明示的に予約されています)。0xD800
0xDFFF
結論として、有効な Unicode コード ポイントは、1 文字または 2unichar
文字を使用して表すことができます。その方法はそこに記載されています。そして、ここに簡単な実装があります:
static NSString *stringWithCodePoint(uint32_t codePoint)
{
// NOTE: As I edited the answer, you'll find a simpler implementation of
// this function below
unichar characters[2];
NSUInteger length;
if ( codePoint <= 0xD7FF || (codePoint >= 0xE000 && codePoint <= 0xFFFF) ) {
characters[0] = codePoint;
length = 1;
}
if ( codePoint >= 0x10000 && codePoint <= 0x10ffff ) {
codePoint -= 0x10000;
characters[0] = 0xD800 + (codePoint >> 10);
characters[1] = 0xDC00 + (codePoint & 0x3ff);
length = 2;
}
else {
length = 0; // invalid code point
}
return [NSString stringWithCharacters:characters length:length];
}
任意の有効なコード ポイントから文字列を生成できるようになったので、前に記述した関数を使用するようにコードを更新する必要があります。
for (int i = 0; i < 10; i++)
[someArray addObject:stringWithCodePoint(0x0001F430 + i)];
編集:NSString
コードポイントから取得するためのより簡単な方法を見つけました。-[NSString initWithBytes:length:encoding:]
およびNSUTF32StringEncoding
エンコーディングを使用して機能します。
static NSString *stringWithCodePoint(uint32_t codePoint)
{
NSString *string = [[NSString alloc] initWithBytes:&codePoint length:4 encoding:NSUTF32StringEncoding];
// You may remove the next 3 lines if you use ARC
#if ! __has_feature(objc_arc)
[string autorelease];
#endif
return string;
}