Get line break in UILabel due to Autolayout
I want to get the text with newlines as UILabel shows up with autoplay on the phone screen. Thank.
For example: if I assign
label.text = "dhasghdsgah dgahjdg ahjgd hkagkhdhk ajsh djkah"
When displayed on screen, it looks like this depending on the width of the screen:
dhasghdsgah dgahjdg ahjgd
hkagkhdhk ajsh
djkah
I want to know where '\ n' was inserted by autodetection.
Please correct me if I missed something.
Find the screenshot: There is no space in the label.
source to share
I solved this problem using this method:
func getArrayOfStringsOnDifferentLines(label: UILabel) -> [String] {
let text:NSString = label.text! as NSString
let font:UIFont = label.font
let rect:CGRect = label.frame
let myFont:CTFont = CTFontCreateWithName(font.fontName as CFString, font.pointSize, nil)
let attStr:NSMutableAttributedString = NSMutableAttributedString(string: text as String)
attStr.addAttribute(String(kCTFontAttributeName), value:myFont, range: NSMakeRange(0, attStr.length))
let frameSetter:CTFramesetter = CTFramesetterCreateWithAttributedString(attStr as CFAttributedString)
let path:CGMutablePath = CGMutablePath()
path.addRect(CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(rect.size.width), height: CGFloat(100000)), transform: .identity)
let frame:CTFrame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, nil)
let lines = CTFrameGetLines(frame) as NSArray
var linesArray = [String]()
for line in lines {
let lineRange = CTLineGetStringRange(line as! CTLine)
let range:NSRange = NSMakeRange(lineRange.location, lineRange.length)
let lineString = text.substring(with: range)
linesArray.append(lineString as String)
}
return linesArray
}
This method returns an array of strings that are on different lines. Now you can use this array as per your need to create a new string with \ n join.
My use:
var stringArray = [String]()
for newItem in self.getLinesArrayOfStringInLabel(label: item.labelToAdd) {
stringArray.append(newItem.replacingOccurrences(of: "\n", with: ""))
}
let stringToSend = stringArray.joined(separator: "\n")
print(stringToSend)
Feel free to ask any detail. Thanks to
source to share
Here's the code for detecting line breaks inside UILabel works
- (int)getLengthForString:(NSString *)str fromFrame:(CGRect)frame withFont:(UIFont *)font
{
int length = 1;
int lastSpace = 1;
NSString *cutText = [str substringToIndex:length];
CGSize textSize = [cutText sizeWithFont:font constrainedToSize:CGSizeMake(frame.size.width, frame.size.height + 500)];
while (textSize.height <= frame.size.height)
{
NSRange range = NSMakeRange (length, 1);
if ([[str substringWithRange:range] isEqualToString:@" "])
{
lastSpace = length;
}
length++;
cutText = [str substringToIndex:length];
textSize = [cutText sizeWithFont:font constrainedToSize:CGSizeMake(frame.size.width, frame.size.height + 500)];
}
return lastSpace;
}
-(NSString*) getLinebreaksWithString:(NSString*)labelText forWidth:(CGFloat)lblWidth forPoint:(CGPoint)point
{
//Create Label
UILabel *label = [[UILabel alloc] init];
label.text = labelText;
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
//Set frame according to string
CGSize size = [label.text sizeWithFont:label.font
constrainedToSize:CGSizeMake(lblWidth, MAXFLOAT)
lineBreakMode:UILineBreakModeWordWrap];
[label setFrame:CGRectMake(point.x , point.y , size.width , size.height)];
//Add Label in current view
[self.view addSubview:label];
//Count the total number of lines for the Label which has NSLineBreakByWordWrapping line break mode
int numLines = (int)(label.frame.size.height/label.font.leading);
//Getting and dumping lines from text set on the Label
NSMutableArray *allLines = [[NSMutableArray alloc] init];
BOOL shouldLoop = YES;
while (shouldLoop)
{
//Getting length of the string from rect with font
int length = [self getLengthForString:labelText fromFrame:CGRectMake(point.x, point.y, size.width, size.height/numLines) withFont:label.font] + 1;
[allLines addObject:[labelText substringToIndex:length]];
labelText = [labelText substringFromIndex:length];
if(labelText.length<length)
shouldLoop = NO;
}
[allLines addObject:labelText];
//NSLog(@"\n\n%@\n",allLines);
return [allLines componentsJoinedByString:@"\n"];
}
How to use:
NSString *labelText = @"We are what our thoughts have made us; so take care about what you think. Words are secondary. Thoughts live; they travel far.";
NSString *stringWithLineBreakChar = [self getLinebreaksWithString:labelText forWidth:200 forPoint:CGPointMake(15, 15)];
NSLog(@"\n\n%@",stringWithLineBreakChar);
You just need to set the parameters required for getLinebreaksWithString and you will get a line with each "\ n" included. Use the label width and starting point that you created in the storyboard.
source to share