2012-08-01 7 views
6

Implementé un teclado personalizado asociado con un campo de texto, por lo que cuando el usuario presiona el botón Eliminar, elimino el último carácter de la cadena y actualizo manualmente el texto actual del campo de texto .Cómo eliminar el último símbolo Unicode de NSString

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

Hasta ahora todo bien.

Ahora, el problema es que el usuario tiene la opción de ingresar algunos símbolos Unicode especiales, estos no son de 1 byte, también pueden ser de 2 bytes, ahora al presionar el botón Eliminar, tengo que quitar todo el símbolo , pero si sigo el enfoque anterior, el usuario tiene que presionar el botón Eliminar dos veces.

Aquí, si lo hago:

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

funciona bien, pero a continuación, los caracteres normales, que son sólo 1 byte, se borran dos veces a la vez.

¿Cómo manejar tales escenarios?

Gracias de antemano.

EDIT:

Es extraño, que si cambiar al teclado de iPhone, que maneja ambos casos adecuadamente. Debe haber alguna forma de hacerlo, hay algo que me falta, pero no puedo descifrar qué.

+0

¿Cómo está agregando los caracteres el teclado personalizado? – Joe

+0

Mi respuesta a esta pregunta puede ayudarlo http://stackoverflow.com/q/11567049/1487063 – Dustin

+0

@Joe: cuando el usuario presiona un botón, capturo el caracter correspondiente, lo anexo al texto actual del campo de texto, y asignarlo como el texto para el campo de texto. –

Respuesta

16

Aquí está el problema. NSStrings están codificados con UTF-16. Muchos glifos Unicode comunes ocupan solo un unichar (un valor sin firmar de 16 bits). Sin embargo, algunos glifos toman dos unichars. Peor aún, algunos glifos se pueden componer o descomponer, por ejemplo, podría ser un punto de código Unicode o podría ser dos: un acento agudo seguido de una e. Esto hace que sea bastante difícil hacer lo que quieres, es decir, eliminar un "personaje" porque es muy difícil decir cuántos unichars toma.

Afortunadamente, NSString tiene un método que ayuda con esto: -rangeOfComposedCharacterSequenceAtIndex:.Lo que necesita hacer es obtener el índice del último unichar, ejecutar este método en él, y el NSRange devuelto le dirá dónde eliminar. Es algo como esto (no probado):

NSUInteger lastCharIndex = [myString length] - 1; // I assume string is not empty 
NSRange rangeOfLastChar = [myString rangeOfComposedCharacterSequenceAtIndex: lastCharIndex]; 
myNewString = [myString substringToIndex: rangeOfLastChar.location]; 
+0

+1 Eso es exactamente lo que estaba buscando. Esto funciona muy bien. Algunos métodos son oculto en el fondo de los documentos para averiguarlo. –

0

Si no puede hacer que esto funcione de forma predeterminada, utilice un bloque if/else y pruebe si el último carácter es parte de un carácter especial. Si es así, use la subcadena a length-2; de lo contrario, use la subcadena a length-1.

+0

¡Gracias por la respuesta! Pero eso no sería un problema, si digamos que el usuario ingresa un carácter desde el teclado, digamos @/#/$, etc. Si verifico si el último carácter es un carácter especial, sería cierto en este caso, y lo haríamos eliminar 2 caracteres, ¿dónde íbamos a eliminar uno? –

+0

Es decir, en su sentencia if, busque los caracteres específicos que le están dando problemas. No los que no son. – Dustin

+0

Oh, sí, pero algunos que me están dando problemas existen en ambos :) Ese es el quid de mi problema. –

0

No sé exactamente cuál es el problema con los caracteres especiales longitud de bytes.

lo que propongo es:

  • tienda longitud de la cadena a un parámetro, antes de añadir los caracteres nuevos
  • Si el usuario selecciona la tecla de retroceso (quitar últimos caracteres) luego quite la cadena desde la última longitud de nueva longitud. Significa, por ejemplo, que la longitud de la última cadena guardada es 5 y la longitud de la nueva cuerda es 7, luego eliminar obtener una nueva cadena con el índice de 0 a 4, por lo que recortará los caracteres restantes.

Esto es al revés que hacer ya que no sé exactamente qué problema internamente.

Pero supongo que lógicamente esta solución debería funcionar.

Enjoy Coding :)

+0

Oh Sí, esto debería funcionar, supongo. Gracias por la respuesta, pero todavía estoy confundido sobre cómo resolverlo con un enfoque más metodológico. He intentado todo tipo de cosas, como convertirlo en NSData, luego eliminar los bytes, para ver qué sucede en realidad, pero fue en vano :( –

Cuestiones relacionadas