uitextfield positionFromPosition: offset no funciona emojis

Estoy intentando implementar mi propio keyboard que contiene emojis. Para este propósito, estoy insertando el emoji en la position del cursor.

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

Estoy publicando el código de inserción aquí. ¿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 text:

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

Al final, resolví esto escribiendo mis propios methods de cálculo de longitud y compensación que countn los 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 la publicación completa del blog http://bit.ly/PT9VSz

Encontré otra forma, me funciona:

 - (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); }