Reputation: 2526
How can I get the NSRange of last line inside one line? (If cursor is at the end of it)
In the image example, I want to get the line range of the text in red box. My code now get the range of whole line (green box):
var currentLineRange: NSRange {
let nsText = self.text as NSString
let currentLineRange = nsText.lineRange(for: self.selectedRange)
return currentLineRange
}
Upvotes: 0
Views: 466
Reputation: 270995
Notice that the range you want is a function of the width with which you have laid out the text, and the font of the text, among many other things. You cannot tell this from a String
alone, as a String
is just some Character
s, and does not have those information. The lineRange
method looks for new line characters in the string, which there evidently aren't, in your Lorem Ipsum paragraph, between "of" and "Lorem", hence that is not counted as a "line".
Assuming this is displayed in a UITextView
(as that is what you have tagged the question with), you can use its layoutManager
to get the range you want.
let selectedRange = textview.selectedRange
let glyphRange = textview.layoutManager.glyphRange(forCharacterRange: selectedRange, actualCharacterRange: nil)
// if the selection starts after the last glyph, glyphRange.lowerBound is not a valid glyph index
// so we need to use the last glyph in that case
let glyphIndex = glyphRange.lowerBound == textview.layoutManager.numberOfGlyphs ?
glyphRange.lowerBound - 1 : glyphRange.lowerBound
var effectiveGlyphRange = NSRange(location: 0, length: 0)
// this gets the *glyph* range of the line
textview.layoutManager.lineFragmentRect(forGlyphAt: glyphIndex, effectiveRange: &effectiveGlyphRange)
let effectiveCharRange = textview.layoutManager.characterRange(forGlyphRange: effectiveGlyphRange, actualGlyphRange: nil)
This code will get the range of the line (aka line fragment) containing the start of the selected range.
If you want to get a range of multiple lines when multiple lines are selected (similar to how lineRange
would have behaved), it should be trivial to modify the code to also get the range of the line containing the end of the selected range, then combine the two ranges.
Upvotes: 2