UITextView get the current line
Asked Answered
U

4

8

Is there a way (crazy hacks welcome) to get the current line as a string of a UITextView? This would include word wrapping, etc. For example, in this case:

enter image description here

The method would return "stack overflow. Isn't it great? I" because that is the current line based on the cursor.

It could also return "This is a test I made for" or "think so", based on the position of the cursor. I have tried working with both the UITextView methods and those of UITextInput protocol.

EDIT:

Here is the code I have attempted to use. The reason I need to find the string is to get it's length, so this is why you'll see UI based code.

NSRange location = self.textView.selectedRange;
NSString *searchString = [self.textView.text substringWithRange:NSMakeRange(0, location)];
CGSize currentStringDimensions = [searchString sizeWithFont:self.textView.font constrainedToSize:CGSizeMake(self.textView.frame.size.width, self.textView.frame.size.height) lineBreakMode:NSLineBreakByWordWrapping];    
float numberOfRows = (currentStringDimensions.width/(self.textView.frame.size.width));
float left = (float)(numberOfRows - (int)numberOfRows) * (self.textView.frame.size.width);

This doesn't work, however. I think it might have something to with words being wrapped or the differently sized characters, but the left value is inconsistent or off after the first line.

Unhinge answered 9/7, 2013 at 20:43 Comment(3)
Show the code you have tried and what it actually returned, how close have you got (I'd say UITextInput is the correct approach).Ranket
Will update main question with itUnhinge
See this - #4421767Quoits
P
2

The following code solution seem to be working. The "self" in this code refers to an instance of UITextView.

- (NSString *) getLineString:(NSRange)range
{
    NSLayoutManager *manager = self.layoutManager;

    // Convert it to a glyph range
    NSRange matchingGlyphRange = [manager glyphRangeForCharacterRange:range actualCharacterRange:NULL];

    // line fragment rect at location range
    CGRect rect = [manager lineFragmentRectForGlyphAtIndex:matchingGlyphRange.location effectiveRange:nil];

    // obtain the line range for the line fragment rect
    NSRange lineRange = [manager glyphRangeForBoundingRect:rect inTextContainer:self.textContainer];

    // extract the string out from lineRange
    return [self.text substringWithRange:lineRange];
}

// ... later
NSLog(@"line %@", [self getLineString:self.selectedRange]);
Paranoid answered 25/7, 2014 at 6:37 Comment(0)
J
2

This worked for me (self = the UITextView)

func getLineString() -> String {
    return (self.text! as NSString).substringWithRange((self.text! as NSString).lineRangeForRange(self.selectedRange))
}
Judd answered 31/3, 2016 at 0:51 Comment(0)
F
0

Swift 5 extension version of Gil's answer:

extension UITextView {
    func getLineString() -> String {
        guard let text = text else { return "" }
        return (text as NSString).substring(with: (text as NSString).lineRange(for: self.selectedRange))
    }
}
Franciscofranciska answered 10/2, 2022 at 8:31 Comment(0)
U
-1

I ended up using the caretRect method of UITextInput to get the offset from the left. Worked flawlessly.

Unhinge answered 16/8, 2013 at 20:15 Comment(3)
@jonathanpeppers Unfortunately, I can't. This was for a paid internship I was doing the previous summer, so the code is inaccessible.Unhinge
Can you re-implement the example on your own and post it? Seems like this is the point of StackOverflow, it shouldn't be the accepted answer unless it actually contains the answer.Ayres
It was such a long time ago that I really can't recall. I'll unaccept this answer though, my apologies.Unhinge

© 2022 - 2024 — McMap. All rights reserved.