My solution is not simple and I do not know if it solves all your problems, but I managed to achieve the effect you wanted.
I've tested it on UILabel
, on different fonts and font sizes, and it worked well.
Here what i've done:
- (NSArray*)getRangesOfLinesForText:(NSString*)text font:(UIFont*)font containerWidth:(float)width {
NSMutableArray *ranges = [[NSMutableArray alloc] init];
NSInteger lastWhiteSpaceIndex = 0;
NSInteger rangeStart = 0;
NSMutableString *substring = [[NSMutableString alloc] init];
for (int i = 0; i < [text length]; i++) {
char c = [text characterAtIndex:i];
[substring appendFormat:@"%c",c];
CGRect substringRect = [substring boundingRectWithSize:CGSizeMake(width, font.capHeight)options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : font} context:nil];
if([[NSCharacterSet whitespaceAndNewlineCharacterSet] characterIsMember:c]) {
lastWhiteSpaceIndex = i;
}
if(substringRect.size.width == 0) {
NSRange range;
if (lastWhiteSpaceIndex != i) {
range = NSMakeRange(rangeStart, lastWhiteSpaceIndex-rangeStart);
[ranges addObject:NSStringFromRange(range)];
substring = [[NSMutableString alloc] init];
i = lastWhiteSpaceIndex;
rangeStart = lastWhiteSpaceIndex+1;
}
}
}
//Last Line
NSRange range = NSMakeRange(rangeStart, [text length]-rangeStart);
[ranges addObject:NSStringFromRange(range)];
return ranges;
}
The method above splits the text
string into separate lines. Unfortunately the method boundingRectWithSize:options:attributes:context:
does not support line break by word wrap, so i had to detect it myself. I achieved that by checking if substringRect.size.width == 0
.
(It changes to zero, when substring becomes too long to fit the line width).
The method returns an array of ranges for every line. (Ranges are converted to NSString
s with NSStringFromRange
).
Example of use:
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectFromString(@"{{0,0},{300,400}}")];
textLabel.numberOfLines = 0;
[self.view addSubview:textLabel];
NSString *text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec luctus quis sapien a rutrum. Vivamus nec leo suscipit nibh rutrum dignissim at vel justo. Maecenas mi orci, ultrices non luctus nec, aliquet et nunc.";
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:text];
for (NSString* stringRange in [self getRangesOfLinesForText:text font:textLabel.font containerWidth:textLabel.frame.size.width]) {
[string addAttribute:NSBackgroundColorAttributeName value:[UIColor greenColor] range:NSRangeFromString(stringRange)];
}
textLabel.attributedText = string;
}