So I'm trying to get the lineFragment
size for each line in a UITextView's NSLayoutManager
. On the first load, it provides values which are larger than the textView layouts.
I have a textview which fills the ViewControllers view with Autolayout.
A basic example is this:
let demotext = """ <Multiline String> """
override func viewWillAppear(_ animated: Bool) {
textview.text = demotext
}
func size(text: String) {
let layoutManager = textview.layoutManager
let numberOfGlyphs = layoutManager.numberOfGlyphs
var currentGlyph = 0
while currentGlyph < numberOfGlyphs {
var glyphRange = NSRange()
let lineSize = layoutManager.lineFragmentUsedRect(forGlyphAt: currentGlyph, effectiveRange: &glyphRange)
print("linesize: \(lineSize)")
currentGlyph = NSMaxRange(glyphRange)
}
}
I tried placing the call in viewDidLoad
, viewDidLayoutSubviews
, viewWillAppear
and also wrote a delegate (which only works if you set allowsNonContiguousLayout
to false) to react on layoutManager(_ layoutManager: didCompleteLayoutFor: atEnd:)
.
The output for the first line after the first start is as follows:
linesize: (0.0, 0.0, 125.6982421875, 16.70703125)
Rotating once to the right and back results in:
linesize: (0.0, 0.0, 107.828125, 13.8)
The line is shorter than the device width, so rotating to landscape once would be enough (it's the same size).
The second value is correct. (I have a visual effect for the text to be able to identify it directly).
I guess I'm missing something basic. Any ideas what it is?
Thanks
Edit:// creating the textview programatically instead of IB solves the problem. But I'm still trying to figure out, why using IB results in this behavior.
Edit2:// This problem does not appear on macOS just iOS