Reputation: 1176
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.
Upvotes: 8
Views: 3292
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
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
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
Reputation: 1176
I ended up using the caretRect method of UITextInput to get the offset from the left. Worked flawlessly.
Upvotes: -1