roozbubu
roozbubu

Reputation: 1176

UITextView get the current line

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.

Upvotes: 8

Views: 3292

Answers (4)

Mostafa ElShazly
Mostafa ElShazly

Reputation: 526

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))
    }
}

Upvotes: 0

Gil
Gil

Reputation: 569

This worked for me (self = the UITextView)

func getLineString() -> String {
    return (self.text! as NSString).substringWithRange((self.text! as NSString).lineRangeForRange(self.selectedRange))
}

Upvotes: 2

Benny Khoo
Benny Khoo

Reputation: 745

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]);

Upvotes: 2

roozbubu
roozbubu

Reputation: 1176

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

Upvotes: -1

Related Questions