Posts Tagged ‘UTF-8’
絵文字を含むNSStringの正確な文字数をカウントする
iPhone/iPad のキーボード設定で「絵文字」というキーボードを追加すると、ガラケーよろしく絵文字を入力できるようになる。なので、何も考えないとUITextFieldなどに絵文字を入力されてしまう可能性がある。ここでアプリの仕様上、絵文字を許容するかしないかという議論は当然起こるが、許容したくないというケースはひとまず置いといて、許容する場合のトピックを取り上げる。
絵文字も他の文字と同様UTF-8であるようだが、絵文字の中には4バイトで表現されるものもあるようで、その4バイトの絵文字を含んだ文字列は [str length]
で得られる文字数が狂ってしまうのだ。そうなるとバリデーションとして文字数制限を設ける場合にうまくない。
この現象はどうやらNSStringクラスのUTF-8の取り扱いに原因があるようだが、不具合だと認識されていれば将来的にSDKの方で対応される可能性がある。それまでは次のような関数で凌ぎたいと思う。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | - (NSUInteger) actualUtf8StringSize:NSString str { const char* cstr = [str UTF8String]; int len = strlen(cstr); NSUInteger count = 0; unsigned char c; for (int i = 0; i < len; i++) { c = (unsigned char)cstr[i]; if (0x00 <= c && c <= 0x7F) { ; } else if (0xC2 <= c && c <= 0xDF) { i += 1; } else if (0xE0 <= c && c <= 0xEF) { i += 2; } else if (0xF0 <= c && c <= 0xF7) { i += 3; } else { continue; } ++count; } return count; } |
これはUTF-8の性質を利用して文字数をカウントしている。UTF-8は文字の1バイト目でその文字が何バイトかを示している。なので、バイト列を先頭から調べて行き、文字のバイト数分スキップしながらカウンタを増加している。ひとつ留意したいのは、バイト列から1バイト取得する時に char
型ではなく unsigned char
型の変数に代入することだ。C言語では常識の範疇だが、慣れていないと見落としやすい。