2012-09-28 12 views
5

Estoy tratando de implementar mi propio teclado que contiene emojis. Para este propósito estoy insertando los emoji en la posición del cursor.uitextfield positionFromPosition: offset no funciona emojis

Esto funciona bien si no existen 4 caracteres emoji de 4 bytes en UITextField. De lo contrario, la aplicación se cuelga.

Estoy publicando aquí el código de inserción. ¿Alguien puede señalar cómo resolver el problema?

UITextField *field = self.textField; 
UITextRange *range = field.selectedTextRange; 
int pos = [field offsetFromPosition:field.beginningOfDocument toPosition:range.end]; 
NSString * firstHalfString = [field.text substringToIndex:pos]; 
NSString * secondHalfString = [field.text substringFromIndex:pos]; 
field.text = [NSString stringWithFormat: @"%@%@%@", firstHalfString, emoticon, secondHalfString]; 
UITextPosition *newPos = [field positionFromPosition:field.beginningOfDocument offset:pos + 1]; 
field.selectedTextRange = [field textRangeFromPosition:newPos toPosition:newPos]; 

esta línea devuelve nil si hay emojis en el texto:

UITextPosition *newPos = [field positionFromPosition:field.beginningOfDocument offset:pos + 1]; 
+0

Gracias! Este es un problema de nicho, pero me molestaba muchísimo. –

Respuesta

4

Al final he resuelto esto escribiendo mi propia longitud y métodos de cálculo de compensación que cuentan caracteres de 4 bytes como 1 carácter no dos

@implementation NSString (UnicodeAdditions) 
-(NSInteger)utf32length { 
    const char* bytes = [self UTF8String]; 
    int length = [self lengthOfBytesUsingEncoding:NSUTF16StringEncoding]; 
    int newLength = 0; 
    for (int i=0; i<length; i++) { 
     if (((unsigned char)bytes[i] >> 7) == 0b00000000) { 
      newLength++; 
     } 
     else if (((unsigned char)bytes[i] >> 5) == 0b00000110) { 
      newLength++; 
      i+=1; 
     } 
     else if (((unsigned char)bytes[i] >> 4) == 0b00001110) { 
      newLength++; 
      i+=2; 
     } 
     else if (((unsigned char)bytes[i] >> 3) == 0b00011110) { 
      newLength++; 
      i+=3; 
     } 
    } 
    return newLength; 
} 


-(NSInteger)utf32offsetWithOffset:(NSInteger)offset { 
    const char* bytes = [self UTF8String]; 
    int length = [self lengthOfBytesUsingEncoding:NSUTF16StringEncoding]; 
    int newLength = 0; 
    for (int i=0; i<length && offset!=0; i++) { 
     if (((unsigned char)bytes[i] >> 7) == 0b00000000) { 
      offset--; 
      newLength++; 
     } 
     else if (((unsigned char)bytes[i] >> 5) == 0b00000110) { 
      offset--; 
      newLength++; 
      i+=1; 
     } 
     else if (((unsigned char)bytes[i] >> 4) == 0b00001110) { 
      offset--; 
      newLength++; 
      i+=2; 
     } 
     else if (((unsigned char)bytes[i] >> 3) == 0b00011110) { 
      offset-=2; 
      newLength++; 
      i+=3; 
     } 
    } 
    return newLength; 
} 

@end 

ver el blog completo http://bit.ly/PT9VSz

2

he encontrado otra manera, funciona para mí:

- (NSRange)findRealRangeForString:(NSString *)text range:(NSRange)range 
{ 
    __block int loc = 0; 
    __block int len = 0; 
    [text enumerateSubstringsInRange:NSMakeRange(0, text.length) options:(NSStringEnumerationByComposedCharacterSequences) usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) 
    { 
     if (substringRange.location < range.location) 
      loc++; 
     else if (substringRange.location < range.location + range.length) 
      len++; 
     else 
      *stop = YES; 
    }]; 
    return NSMakeRange(loc, len); 
} 
+0

Tenga en cuenta que el texto es el texto completo, y ese rango es el rango del texto que desea encontrar el verdadero rango de. –

+1

@AlexBeals sure. Parece que el nombre de mi función no es muy claro. Gracias por la descripción. La función intenta corregir determinado rango de cadena para no dividir símbolos de múltiples caracteres. – k06a