Get Each Line of Text in a Uilabel

How to get text / String from nth line of UILabel?

I don't think there's a native way for doing this (like a "takethenline" method).

I can figure out a tricky solution but I'm not sure is the best one.

You could split your label into an array of words.

Then you could loop the array and check the text height until that word like this:

NSString *texttocheck;
float old_height = 0;
int linenumber = 0;

for (x=0; x<[wordarray lenght]; x++) {
texttocheck = [NSString stringWithFormat:@"%@ %@", texttocheck, [wordarray objectAtIndex:x]];

float height = [text sizeWithFont:textLabel.font
constrainedToSize:CGSizeMake(textLabel.bounds.size.width,99999)
lineBreakMode:UILineBreakModeWordWrap].height;

if (old_height < height) {
linenumber++;
}
}

If height changes, it means there's a line break before the word.

I can't check if the syntax is written correctly now, so you have to check it yourself.

Multiple lines of text in UILabel

Set the line break mode to word-wrapping and the number of lines to 0:

// Swift
textLabel.lineBreakMode = .byWordWrapping
textLabel.numberOfLines = 0

// Objective-C
textLabel.lineBreakMode = NSLineBreakByWordWrapping;
textLabel.numberOfLines = 0;

// C# (Xamarin.iOS)
textLabel.LineBreakMode = UILineBreakMode.WordWrap;
textLabel.Lines = 0;

Restored old answer (for reference and devs willing to support iOS below 6.0):

textLabel.lineBreakMode = UILineBreakModeWordWrap;
textLabel.numberOfLines = 0;

On the side: both enum values yield to 0 anyway.

Get string of first line in a UILabel

1.Add CoreText.framework. 2. Import #import CoreText/CoreText.h>.
Then use below method -

-(NSArray *)getLinesArrayOfStringInLabel:(UILabel *)label
{
NSString *text = [label text];
UIFont *font = [label font];
CGRect rect = [label frame];

CTFontRef myFont = CTFontCreateWithName(( CFStringRef)([font fontName]), [font pointSize], NULL);
NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text];
[attStr addAttribute:(NSString *)kCTFontAttributeName value:( id)myFont range:NSMakeRange(0, attStr.length)];

CFRelease(myFont);

CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString(( CFAttributedStringRef)attStr);

CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(0,0,rect.size.width,100000));

CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);

NSArray *lines = ( NSArray *)CTFrameGetLines(frame);

NSMutableArray *linesArray = [[NSMutableArray alloc]init];

for (id line in lines)
{
CTLineRef lineRef = ( CTLineRef )line;
CFRange lineRange = CTLineGetStringRange(lineRef);
NSRange range = NSMakeRange(lineRange.location, lineRange.length);

NSString *lineString = [text substringWithRange:range];

CFAttributedStringSetAttribute((CFMutableAttributedStringRef)attStr, lineRange, kCTKernAttributeName, (CFTypeRef)([NSNumber numberWithFloat:0.0]));
CFAttributedStringSetAttribute((CFMutableAttributedStringRef)attStr, lineRange, kCTKernAttributeName, (CFTypeRef)([NSNumber numberWithInt:0.0]));

//NSLog(@"''''''''''''''''''%@",lineString);
[linesArray addObject:lineString];

}
[attStr release];

CGPathRelease(path);
CFRelease( frame );
CFRelease(frameSetter);

return (NSArray *)linesArray;
}

I found this answer from below url - How to get text from nth line of UILabel?

NSString *firstLineString = [[self getLinesArrayOfStringInLabel:yourLabel] objectAtIndex:0];

How to find actual number of lines of UILabel?

Firstly set text in UILabel

First Option :

Firstly calculate height for text according to font :

NSInteger lineCount = 0;
CGSize labelSize = (CGSize){yourLabel.frame.size.width, MAXFLOAT};
CGRect requiredSize = [self boundingRectWithSize:labelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: yourLabel.font} context:nil];

Now calculate number of lines :

int charSize = lroundf(yourLabel.font.lineHeight);
int rHeight = lroundf(requiredSize.height);
lineCount = rHeight/charSize;
NSLog(@"No of lines: %i",lineCount);

Second Option :

 NSInteger lineCount = 0;
CGSize textSize = CGSizeMake(yourLabel.frame.size.width, MAXFLOAT);
int rHeight = lroundf([yourLabel sizeThatFits:textSize].height);
int charSize = lroundf(yourLabel.font.lineHeight);
lineCount = rHeight/charSize;
NSLog(@"No of lines: %i",lineCount);

Resulting lines of UILabel with UILineBreakModeWordWrap

I don't think there is any silver bullet for this.

Here is a category method that seems to work for the few basic test cases I threw at it. No guarantees it won't break with something complex!

The way it works is to move through the string testing to see if a range of words fits in the width of the label. When it calculates that the current range is too wide it records the last-fitting range as a line.

I don't claim this is efficient. A better way may just to be to implement your own UILabel...

@interface UILabel (Extensions)

- (NSArray*) lines;

@end

@implementation UILabel (Extensions)

- (NSArray*) lines
{
if ( self.lineBreakMode != UILineBreakModeWordWrap )
{
return nil;
}

NSMutableArray* lines = [NSMutableArray arrayWithCapacity:10];

NSCharacterSet* wordSeparators = [NSCharacterSet whitespaceAndNewlineCharacterSet];

NSString* currentLine = self.text;
int textLength = [self.text length];

NSRange rCurrentLine = NSMakeRange(0, textLength);
NSRange rWhitespace = NSMakeRange(0,0);
NSRange rRemainingText = NSMakeRange(0, textLength);
BOOL done = NO;
while ( !done )
{
// determine the next whitespace word separator position
rWhitespace.location = rWhitespace.location + rWhitespace.length;
rWhitespace.length = textLength - rWhitespace.location;
rWhitespace = [self.text rangeOfCharacterFromSet: wordSeparators options: NSCaseInsensitiveSearch range: rWhitespace];
if ( rWhitespace.location == NSNotFound )
{
rWhitespace.location = textLength;
done = YES;
}

NSRange rTest = NSMakeRange(rRemainingText.location, rWhitespace.location-rRemainingText.location);

NSString* textTest = [self.text substringWithRange: rTest];

CGSize sizeTest = [textTest sizeWithFont: self.font forWidth: 1024.0 lineBreakMode: UILineBreakModeWordWrap];
if ( sizeTest.width > self.bounds.size.width )
{
[lines addObject: [currentLine stringByTrimmingCharactersInSet:wordSeparators]];
rRemainingText.location = rCurrentLine.location + rCurrentLine.length;
rRemainingText.length = textLength-rRemainingText.location;
continue;
}

rCurrentLine = rTest;
currentLine = textTest;
}

[lines addObject: [currentLine stringByTrimmingCharactersInSet:wordSeparators]];

return lines;
}

@end

use like this:

NSArray* lines = [_theLabel lines];

int count = [lines count];

How to find and replace UILabel's value on a specific line?

Assuming from your screen shot that each line is separated by a newline character you can split the text based on that.

Here is an example in Swift 3:

if let components = label.text?.components(separatedBy: "\n"), components.count > 1 {
let secondLine = components[2]
let editedSecondLine = secondLine + "edited"
label.text = label.text?.replacingOccurrences(of: secondLine, with: editedSecondLine)
}

You should make sure there is a value at whatever index your interested in. This example makes sure that there are more than a single component before retrieving the value.

You can then replace the second line with your edited line.

Hope that helps.



Related Topics



Leave a reply



Submit