I am trying to set an attributed string within NSTextView. I want to increase its height based on its content, initially it is set to some default value.
So I tried
Based on @Peter Hosey's answer, here is an extension to NSTextView in Swift 4.2:
extension NSTextView {
var contentSize: CGSize {
get {
guard let layoutManager = layoutManager, let textContainer = textContainer else {
print("textView no layoutManager or textContainer")
return .zero
}
layoutManager.ensureLayout(for: textContainer)
return layoutManager.usedRect(for: textContainer).size
}
}
}
NSTextView *textView = [[NSTextView alloc] init];
textView.font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
textView.string = @"Lorem ipsum";
[textView.layoutManager ensureLayoutForTextContainer:textView.textContainer];
textView.frame = [textView.layoutManager usedRectForTextContainer:textView.textContainer];
+ (float)heightForString:(NSString *)myString font:(NSFont *)myFont andWidth:(float)myWidth andPadding:(float)padding {
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:myString];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize:NSMakeSize(myWidth, FLT_MAX)];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[layoutManager addTextContainer:textContainer];
[textStorage addLayoutManager:layoutManager];
[textStorage addAttribute:NSFontAttributeName value:myFont
range:NSMakeRange(0, textStorage.length)];
textContainer.lineFragmentPadding = padding;
(void) [layoutManager glyphRangeForTextContainer:textContainer];
return [layoutManager usedRectForTextContainer:textContainer].size.height;
}
I did the function using this reference: Documentation
Example:
float width = textView.frame.size.width - 2 * textView.textContainerInset.width;
float proposedHeight = [Utils heightForString:textView.string font:textView.font andWidth:width
andPadding:textView.textContainer.lineFragmentPadding];
Ask the text view for its layout manager and its text container. Then, force the layout manager to perform layout, and then ask the layout manager for the used rectangle for the text container.
See also the Text System Overview.