I know NSString has methods that determine the frame size for it, using NSString UIKit Additions, sizeWithFont......
How about the other way around? I mean if I have a fixed frame size, how do I know how many characters or words for a NSString that can fit into it?
If I know this, I can cut off the NSString easily.
thanks
It might not be the most elegant solution, but you could do something like this:
- (NSString *)string:(NSString *)sourceString reducedToWidth:(CGFloat)width withFont:(UIFont *)font {
if ([sourceString sizeWithFont:font].width <= width)
return sourceString;
NSMutableString *string = [NSMutableString string];
for (NSInteger i = 0; i < [sourceString length]; i++) {
[string appendString:[sourceString substringWithRange:NSMakeRange(i, 1)]];
if ([string sizeWithFont:font].width > width) {
if ([string length] == 1)
return nil;
[string deleteCharactersInRange:NSMakeRange(i, 1)];
break;
}
}
return string;
}
Then call it like this:
NSString *test = @"Hello, World!";
CGFloat width = 40.0;
UIFont *font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
NSString *reducedString = [self string:test reducedToWidth:width withFont:font];
NSLog(@"%@", reducedString);
You cannot know/determine the number of characters that fits in a UILabel with fixed width because some characters are smaler than others, eg l and m.
There are two options:
- Use Mono-Space-Fonts (each character has also a fixed width). Then determine the width for one char in your font with your font-size and calculate the number of chars
- Allow any number of characters and check on insert if the inserted characters fit.
You have to know what behaviour you want to have. What should happen if there is text that does not fit. If you only want to truncate (like the solution of mortenfast does) then just use UILineBreakModeTailTruncation
for the lineBreakMode
-property of your UILabel
(there are more options, like TruncateHead, Clip, Word Wrap)
Thanks @Morten. I've updated the sample code to handle word separation. It also eliminates extra spaces in between words. It has not been tested in the field, but my tests have, thus far, proven OK. Please update at your leisure if you find improvements or bug/glitch fixes.
-(NSString*)string:(NSString*)sourceString reducedToWidth:(CGFloat)width withFont:(UIFont*)font {
// if full string is within bounds, simply return the full string
if( [sourceString sizeWithFont:font].width <= width ) return sourceString;
// break up string into words. if <= 1 word, return original string
NSArray* words = [sourceString componentsSeparatedByString:@" "];
NSInteger numWords = [words count];
if( numWords <= 1 ) return sourceString;
// our return var. we populate as we go
NSMutableString* str = [NSMutableString string];
// temp var to test with before adding to return string
NSMutableString* strTemp = [NSMutableString string];
// string to hold word LESS spaces
NSString* strWordTemp = nil;
// the word we're currently on
NSInteger numWord = 0;
// whether we need to add a space (when not last word)
Boolean addSpace = NO;
// loop through our words....
for( NSString* strWord in words ) {
// which word we're on
numWord++;
// eliminate white space
strWordTemp = [strWord stringByReplacingOccurrencesOfString:@" " withString:@""];
// if this word is empty or was a space(s), skip it
if( [strWordTemp isEqualToString:@""] ) continue;
// append to temp string
[strTemp appendString:strWordTemp];
// if we're still within the bounds...
if( [strTemp sizeWithFont:font].width <= width ) {
// default = no extra space
addSpace = NO;
// if we're not the last word, add a space & check for length
if( numWord < numWords ) {
[strTemp appendString:@" "];
// if adding space made it too long, then just don't add it!
if( [strTemp sizeWithFont:font].width > width ) {
// it was too long with space, so we'll just add word
[str appendString:strWordTemp];
break;
}
// otherwise, it's OK to add the space
else addSpace = YES;
}
// append to return string and continue
[str appendFormat:@"%@%@", strWordTemp, ( addSpace ? @" " : @"" )];
}
// otherwise, we're done
else break;
}
// return our result
return str;
}
Or you just just use the lineBreak property and set it to NSLineBreakByCharWrapping and move on with your life. https://stackoverflow.com/a/29088337/951349