Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
711 views
in Technique[技术] by (71.8m points)

ios - Truncate string containing emoji or unicode characters at word or character boundaries

The Problem

How can I truncate a string at a given length without annihilating a unicode character that might be smack in the middle of my length? How can one determine the index of the beginning of a unicode character in a string so that I can avoid creating ugly strings. The square with half of an A visible is the location of another emoji character which has been truncated.

-(NSMutableAttributedString*)constructStatusAttributedStringWithRange:(CFRange)range

NSString *original = [_postDictionay objectForKey:@"message"];

NSMutableString *truncated = [NSMutableString string];

NSArray *components = [original componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];

for(int x=0; x<[components count]; x++)
{
    //If the truncated string is still shorter then the range desired. (leave space for ...)
    if([truncated length]+[[components objectAtIndex:x] length]<range.length-3)
    {
        //Just checking if its the first word
        if([truncated length]==0 && x==0)
        {
            //start off the string
            [truncated appendString:[components objectAtIndex:0]];
        }
        else
        {
            //append a new word to the string
            [truncated appendFormat:@" %@",[components objectAtIndex:x]];
        }

    }
    else
    {
        x=[components count];
    }
}

if([truncated length]==0 || [truncated length]< range.length-20)
{
    truncated = [NSMutableString stringWithString:[original substringWithRange:NSMakeRange(range.location, range.length-3)]];
}

[truncated appendString:@"..."];

NSMutableAttributedString *statusString = [[NSMutableAttributedString alloc]initWithString:truncated];
[statusString addAttribute:(id)kCTFontAttributeName value:[StyleSingleton streamStatusFont] range:NSMakeRange(0, [statusString length])];
[statusString addAttribute:(id)kCTForegroundColorAttributeName value:(id)[StyleSingleton streamStatusColor].CGColor range:NSMakeRange(0, [statusString length])];

return statusString;

}

UPDATE Thanks to the answer, was able to use one simple function for my needs!

-(NSMutableAttributedString*)constructStatusAttributedStringWithRange:(CFRange)range
{
NSString *original = [_postDictionay objectForKey:@"message"];

NSMutableString *truncated = [NSMutableString stringWithString:[original substringWithRange:[original rangeOfComposedCharacterSequencesForRange:NSMakeRange(range.location, range.length-3)]]];
[truncated appendString:@"..."];

NSMutableAttributedString *statusString = [[NSMutableAttributedString alloc]initWithString:truncated];
[statusString addAttribute:(id)kCTFontAttributeName value:[StyleSingleton streamStatusFont] range:NSMakeRange(0, [statusString length])];
[statusString addAttribute:(id)kCTForegroundColorAttributeName value:(id)[StyleSingleton streamStatusColor].CGColor range:NSMakeRange(0, [statusString length])];

return statusString;

}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

NSString has a method rangeOfComposedCharacterSequencesForRange that you can use to find the enclosing range in the string that contains only complete composed characters. For example

NSString *s =  @"??";
NSRange r = [s rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, 1)];

gives the range { 0, 2 } because the Emoji character is stored as two UTF-16 characters (surrogate pair) in the string.

Remark: You could also check if you can simplify your first loop by using

enumerateSubstringsInRange:options:usingBlock

with the NSStringEnumerationByWords option.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...