2

一連の絵文字アイコンを配列に追加したいと考えています。以前の質問から、絵文字アイコンをNSString. 次に、ループを作成して、これらのアイコンを配列に追加します。ユニコードは特定の範囲にあるため、これはかなり簡単なはずなので、次のようにする必要があります。

for (int i = 0; i < 10; i++)
    [someArray addObject:[NSString stringWithFormat:@"\U0001F43%i", i]];

問題は、そうすると次のようなエラーが表示されることです。

不完全なユニバーサル キャラクター名です。

これを行う方法を知っている人はいますか?

4

3 に答える 3

4

これは、エスケープ シーケンス\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+0000U+10FFFF. 次に、実装は、文字を使用してそれらのコード ポイントを表す方法を決定します。実装は、すべての有効なコード ポイントを表すことができる限り、必要な任意のデータ型を文字として使用できます。最も簡単な解決策は、32 ビット長の整数を使用することですが、使用するコード ポイントのほとんどが最初の Unicode プラン ( U+0000U+FFFF) にあるため、大量のメモリが必要になります。そのため、 16 ビット長の文字を使用する UTF-16 エンコーディングNSStringでコード ポイントを格納します。

UTF-16 では、それ以降のすべてのコード ポイントはU+FFFF、範囲内の文字のペア (サロゲート ペアと呼ばれます) を使用して格納されます(対応するコード ポイントは、Unicode 標準で明示的に予約されています)。0xD8000xDFFF

結論として、有効な 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;
}
于 2012-06-26T19:47:48.133 に答える
0

この同様の質問に注意してください。その回答の1つが説明しているように、文字列リテラルのバックスラッシュエスケープはコンパイル時に評価されます。\Uxxxxエスケープを使用して Unicode 文字を作成する場合は、文字列リテラル内xxxxのすべてが数字である必要があります。

代わりにできることは、別の答えによると、フォーマット指定子をエスケープ%Cと一緒に使用するのでは\Uxxxxなく、単独で使用し、完全な文字コードを整数として渡すことです。(実際にはwchar_t、現在 Mac OS X では 32 ビット整数であり、探している文字コードが 16 ビットを超えるため必要になります。) これを基数と組み合わせるには、次のことができます。整数を追加するだけです:

wchar_t base = 0x0001F430; // unfamiliar? we start with 0x for hexadecimal integers
for (int i = 0; i < 10; i++)
    [someArray addObject:[NSString stringWithFormat:@"%C", base + i]];

ただし、明示的にstringWithCharacters:(16-bit) を取るunicharため、文字シーケンスを使用して絵文字を UTF-16 でエンコードする必要があります。

于 2012-06-26T19:48:50.093 に答える
0

%Cの代わりに使用%i

それで:

[someArray addObject:[NSString stringWithFormat:@"\U0001F43%C", i]];
于 2012-06-26T19:04:25.783 に答える