6

テキスト フィールドに関連付けられたカスタム キーボードを実装したので、ユーザーが削除ボタンを押すと、文字列から最後の文字を削除し、現在のテキスト フィールドのテキストを手動で更新します。

NSRange range = NSMakeRange(currentTextFieldString.length-1, 1);
[currentTextFieldString replaceCharactersInRange:range withString:@""];

ここまでは順調ですね。

さて、問題は、ユーザーがいくつかの特別な Unicode 記号を入力するオプションを持っていることです。これらは 1 バイトではなく、2 バイトにすることもできます。削除ボタンを押すと、記号全体を削除する必要がありますが、上記のアプローチに従うと、ユーザーは削除ボタンを 2 回押す必要があります。

ここで、もしそうなら:

NSRange range = NSMakeRange(currentTextFieldString.length-2, 2);
[currentTextFieldString replaceCharactersInRange:range withString:@""];

正常に動作しますが、通常の文字は 1 バイトだけで、一度に 2 回削除されます。

そのようなシナリオをどのように処理しますか?

前もって感謝します。

編集:

奇妙なことに、iPhone キーボードに切り替えると、両方のケースが適切に処理されます。それを行うには何らかの方法があるに違いありません。私には欠けているものがありますが、何がわからないのですか。

4

3 に答える 3

18

これが問題です。NSString は UTF-16 を使用してエンコードされます。多くの一般的な Unicode グリフは、1 つのみunichar(16 ビット符号なし値) を使用します。ただし、一部のグリフは 2 つのユニ文字を使用します。さらに悪いことに、一部のグリフは合成または分解できます。egé は 1 つの Unicode コード ポイントである場合もあれば、鋭アクセント記号の後に e が続く 2 つの場合もあります。これにより、1 つの「文字」を削除するなど、やりたいことを行うのが非常に難しくなります。

幸いなことに、NSString にはこれに役立つメソッドがあります: -rangeOfComposedCharacterSequenceAtIndex:。あなたがする必要があるのは、最後の unichar のインデックスを取得し、それに対してこのメ​​ソッドを実行することです。返された NSRange は、どこから削除するかを教えてくれます。次のようになります(テストされていません):

NSUInteger lastCharIndex = [myString length] - 1; // I assume string is not empty
NSRange rangeOfLastChar = [myString rangeOfComposedCharacterSequenceAtIndex: lastCharIndex];
myNewString = [myString substringToIndex: rangeOfLastChar.location];
于 2012-08-01T13:51:22.280 に答える
0

これをデフォルトで機能させることができない場合は、if / elseブロックを使用して、最後の文字が特殊文字の一部であるかどうかをテストします。そうである場合は、部分文字列toをlength-2使用し、そうでない場合は、部分文字列toを使用しlength-1ます。

于 2012-08-01T13:30:18.143 に答える
0

特殊文字のバイト長に何が問題なのか正確にはわかりません。

私が提案するのは:

  • 新しい文字を追加する前に、文字列の長さをパラメーターに保存します
  • ユーザーがバックスペース (最後の文字を削除) を選択した場合、文字列を最後の長さから新しい長さまで削除します。たとえば、最後に保存された文字列の長さが 5 で、新しい文字列の長さが 7 の場合、削除すると、インデックスが 0 から 4 の新しい文字列が取得されるため、残りの文字がトリミングされます。

内部で何が問題なのか正確にはわからないので、これは逆です。

しかし、論理的には、このソリューションは機能するはずです。

コーディングをお楽しみください :)

于 2012-08-01T13:32:41.770 に答える