2012-09-28 13 views
5

Emojileri içeren kendi klavyemi uygulamaya çalışıyorum. Bu amaçla, imleç konumuna emoji ekliyorum.uitextfield positionFromPosition: offset çalışmıyor emojis

Bu, UITextField'da 4 baytlık emoji karakterleri yoksa iyi çalışır. Aksi takdirde uygulama çöktü.

Ekleme kodunu buraya gönderiyorum. Birisi sorunun nasıl çözüleceğine işaret edebilir mi?

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

bu hat metinde emoji'yi varsa nil döndürür: 1 karakter olarak 4 bayt karakterleri saymak Ben kendi uzunluğunun yazarak bu çözüldü sonunda

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

teşekkür ederiz! Bu çok hoş bir problem ama benim dışımda canımı sıkıyordu. –

cevap

4

ve ofset hesaplama yöntemleri değil, iki.

@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 

Ben başka bir yol buldum http://bit.ly/PT9VSz

2

tam Blog post bakın, benim için çalışıyor:

- (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

Metnin tam metin olduğunu ve bu aralığın gerçek aralığını bulmak istediğiniz metnin aralığı olduğunu unutmayın. –

+1

@AlexBeals emin. Fonksiyon ismimin çok net olmadığı anlaşılıyor. Açıklama için teşekkürler. İşlev, çok karakterli sembolleri bölmek için verilen dizgi aralığını düzeltmeye çalışır. – k06a