Categories
Development

NSString truncate function for Objective C/iPhone SDK

So far as I can tell, the iPhone SDK exposes no method to truncate an NSString to a given width (in pixels). This function obviously exists since it is used when drawing UILabels, and you can even draw truncated text with the method:
[cc lang=”objc” inline=”true” width=”0″ theme=”geshi”]
– (CGSize)drawInRect:(CGRect)rect withFont:(UIFont*)font lineBreakMode:(UILineBreakMode)lineBreakMode[/cc]
… but there’s no way to read-back the rendered text.

A quick search of the ‘net revealed some methods which would truncate a string based on the number of characters, but nothing to perform the operation based on the rendered width in pixels.

Here’s my code, from the new release of Fast Fonts which has now been updated to display iPad fonts correctly.

[cc lang=”objc” width=”0″ line_numbers=”true” theme=”geshi”]
//
// NSString-truncateToSize
// Fast Fonts
//
// Created by Stuart Shelton on 28/03/2010.
// Copyright 2010 Stuart Shelton. All rights reserved.
//

@interface NSString (truncateToSize)

– (NSString *)truncateToSize: (CGSize)size withFont: (UIFont *)font lineBreakMode: (UILineBreakMode)lineBreakMode;
– (NSString *)truncateToSize: (CGSize)size withFont: (UIFont *)font lineBreakMode: (UILineBreakMode)lineBreakMode withAnchor: (NSString *)anchor;
– (NSString *)truncateToSize: (CGSize)size withFont: (UIFont *)font lineBreakMode: (UILineBreakMode)lineBreakMode withStartingAnchor: (NSString *)startingAnchor withEndingAnchor: (NSString *)endingAnchor;

@end

@implementation NSString (truncateToSize)

– (NSString *)truncateToSize: (CGSize)size withFont: (UIFont *)font lineBreakMode: (UILineBreakMode)lineBreakMode {
return [self truncateToSize: size withFont: font lineBreakMode: lineBreakMode withStartingAnchor: nil withEndingAnchor: nil];
} /* (NSString *)truncateToSize: withFont: lineBreakMode: */

– (NSString *)truncateToSize: (CGSize)size withFont: (UIFont *)font lineBreakMode: (UILineBreakMode)lineBreakMode withAnchor: (NSString *)anchor {
return [self truncateToSize: size withFont: font lineBreakMode: lineBreakMode withStartingAnchor: anchor withEndingAnchor: anchor];
} /* (NSString *)truncateToSize: withFont: lineBreakMode: withAnchor: */

– (NSString *)truncateToSize: (CGSize)size withFont: (UIFont *)font lineBreakMode: (UILineBreakMode)lineBreakMode withStartingAnchor: (NSString *)startingAnchor withEndingAnchor: (NSString *)endingAnchor {
if( !( lineBreakMode & ( UILineBreakModeHeadTruncation | UILineBreakModeMiddleTruncation | UILineBreakModeTailTruncation ) ) )
return self;
if( [self sizeWithFont: font].width [ellipsis length] + 1 && [truncatedString sizeWithFont: font].width > size.width) {
// Replace our ellipsis and one additional following character with our ellipsis
NSRange range = NSMakeRange( start, [ellipsis length] + 1 );
[truncatedString replaceCharactersInRange: range withString: ellipsis];
targetLength–;
}
break;

case UILineBreakModeMiddleTruncation:
{
NSUInteger leftEnd = start + ( targetLength / 2 );
NSUInteger rightStart = leftEnd + 1;

if( leftEnd + 1 start + 1 && rightStart size.width) {
CGFloat leftLength = [left sizeWithFont: font].width;
CGFloat rightLength = [right sizeWithFont: font].width;

// Shorten string of longest width
if( leftLength > rightLength ) {
[left deleteCharactersInRange: NSMakeRange( [left length] – 1, 1 )];
leftEnd–;
} else { /* ( leftLength [ellipsis length] + 1 && [truncatedString sizeWithFont: font].width > size.width) {
// Remove last character
NSRange range = NSMakeRange( –end, 1);
[truncatedString deleteCharactersInRange: range];
// Replace original last-but-one (now last) character with our ellipsis…
range = NSMakeRange( end – [ellipsis length], [ellipsis length] );
[truncatedString replaceCharactersInRange: range withString: ellipsis];
targetLength–;
}
break;
}

NSString *result = [NSString stringWithString: truncatedString];
[truncatedString release];
return result;
} /* (NSString *)truncateToSize: withFont: lineBreakMode: withStartingAnchor: withEndingAnchor: */

@end
[/cc]

NSString-truncateToSize.h
NSString-truncateToSize.m

2 replies on “NSString truncate function for Objective C/iPhone SDK”

Leave a Reply