UITextView get the current line

2019-03-20 14:52发布

问题:

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:

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.

回答1:

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


回答2:

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



回答3:

This worked for me (self = the UITextView)

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