How to truncate an NSString based on the graphical width?
Asked Answered
S

2

6

In UILabel there's functionality to truncate labels using different truncation techniques (UILineBreakMode). In NSString UIKit Additions there is a similar functionality for drawing strings.

However, I found no way to access the actual truncated string. Is there any other way to get a truncated string based on the (graphical) width for a given font?

I'd like to have a category on NSString with this method:

-(NSString*)stringByTruncatingStringWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode
Screenplay answered 15/2, 2010 at 14:3 Comment(0)
C
6

One option is trying different sizes by looping until you get the right width. I.e. start with the full string, if that's wider than what you need, replace the last two characters with an ellipsis character. Loop until it's narrow enough.

If you think you'll be working with long strings, you can binary search your way towards the truncation point to make it a bit faster.

Contend answered 15/2, 2010 at 14:51 Comment(1)
Thanks Uli, good idea. Works like a charm. See the code in the other comment.Screenplay
S
17
- (NSString*)stringByTruncatingStringWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode {
    NSMutableString *resultString = [[self mutableCopy] autorelease];
    NSRange range = {resultString.length-1, 1};

    while ([resultString boundingRectWithSize:CGSizeMake(FLT_MAX, FLT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attributes context:nil].size.width > width) {
        // delete the last character
        [resultString deleteCharactersInRange:range];
        range.location--;
        // replace the last but one character with an ellipsis
        [resultString replaceCharactersInRange:range withString:truncateReplacementString];
    }
    return resultString;
}

Note that since iOS 6 this method is not safe to run on background threads anymore.

Screenplay answered 15/2, 2010 at 22:49 Comment(2)
Probably, should be updated with iOS method - boundingRectWithSize:options:attributes:context:, due to deprecation.Twentieth
@Twentieth indeed. Done.Screenplay
C
6

One option is trying different sizes by looping until you get the right width. I.e. start with the full string, if that's wider than what you need, replace the last two characters with an ellipsis character. Loop until it's narrow enough.

If you think you'll be working with long strings, you can binary search your way towards the truncation point to make it a bit faster.

Contend answered 15/2, 2010 at 14:51 Comment(1)
Thanks Uli, good idea. Works like a charm. See the code in the other comment.Screenplay

© 2022 - 2024 — McMap. All rights reserved.