【问题标题】:uitextfield positionFromPosition:offset not working emojisuitextfield positionFromPosition:偏移量不起作用表情符号
【发布时间】:2014-01-11 18:49:16
【问题描述】:

我正在尝试实现我自己的包含表情符号的键盘。 为此,我将表情符号插入光标位置。

如果 UITextField 中不存在 4 字节的表情符号字符,这将正常工作。否则应用程序会崩溃。

我在这里发布插入代码。有人能指出如何解决这个问题吗?

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];

如果文本中有表情符号,则此行返回 nil:

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

【问题讨论】:

  • 谢谢!这是一个小众问题,但它让我很恼火。

标签: iphone objective-c ios uitextfield emoji


【解决方案1】:

最后我通过编写自己的长度和偏移量计算方法解决了这个问题,将 4 字节字符计为 1 个字符,而不是两个。

@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

查看完整的博文http://bit.ly/PT9VSz

【讨论】:

    【解决方案2】:

    我找到了另一种方法,它对我有用:

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

    【讨论】:

    • 注意text是全文,而那个范围就是你要查找的真正范围的文本范围。
    • @AlexBeals 确定。看起来我的函数名称不是很清楚。感谢您的描述。函数试图纠正给定的字符串范围,而不是分割多字符符号。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-02
    • 2012-05-12
    相关资源
    最近更新 更多