Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect moment when newline starts in UITextView

I try to detect when carriage goes at new line in UITextView. I can detect it by comparison total later width with UITextView width:

CGSize size = [textView.text sizeWithAttributes:textView.typingAttributes];
if(size.width > textView.bounds.size.width)
      NSLog (@"New line");

But it dose not work proper way because -sizeWithAttributes:textView returns only width of letters without indentation width. Help please solve this.

like image 568
mriddi Avatar asked Nov 15 '13 19:11

mriddi


4 Answers

This is how I would do it:

  • Get the UITextPosition of the last character.
  • Call caretRectForPosition on your UITextView.
  • Create a CGRect variable and initially store CGRectZero in it.
  • In your textViewDidChange: method, call caretRectForPosition: by passing the UITextPosition.
  • Compare it with the current value stored in the CGRect variable. If the new y-origin of the caretRect is greater than the last one, it means a new line has been reached.

Sample code:

CGRect previousRect = CGRectZero;
- (void)textViewDidChange:(UITextView *)textView{

    UITextPosition* pos = yourTextView.endOfDocument;//explore others like beginningOfDocument if you want to customize the behaviour
    CGRect currentRect = [yourTextView caretRectForPosition:pos];

    if (currentRect.origin.y > previousRect.origin.y){
            //new line reached, write your code
        }
    previousRect = currentRect;

}

Also, you should read the documentation for UITextInput protocol reference here. It is magical, I'm telling you.

Let me know if you have any other issues with this.

like image 190
n00bProgrammer Avatar answered Oct 22 '22 00:10

n00bProgrammer


For Swift use this

previousRect = CGRectZero

 func textViewDidChange(textView: UITextView) {

        var pos = textView.endOfDocument
        var currentRect = textView.caretRectForPosition(pos)
        if(currentRect.origin.y > previousRect?.origin.y){
            //new line reached, write your code
        }
        previousRect = currentRect

    }
like image 21
Sourav Gupta Avatar answered Oct 22 '22 00:10

Sourav Gupta


answer of @n00bProgrammer in Swift-4 with more precise line break detection.

@n00bProgrammer answer is perfect except one thing it reacts differently when the user starts typing in a first line, it presents that Started New Line too.
Overcoming issue, here is the refined code

    var previousRect = CGRect.zero
    func textViewDidChange(_ textView: UITextView) {
        let pos = textView.endOfDocument
        let currentRect = textView.caretRect(for: pos)
        self.previousRect = self.previousRect.origin.y == 0.0 ? currentRect : self.previousRect
        if currentRect.origin.y > self.previousRect.origin.y {
            //new line reached, write your code
            print("Started New Line")
        }
        self.previousRect = currentRect
    }
like image 41
Kiran Jasvanee Avatar answered Oct 21 '22 23:10

Kiran Jasvanee


You can use the UITextViewDelegate

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText: (NSString *)text
{
     BOOL newLine = [text isEqualToString:@"\n"];
     if(newLine)
     {
          NSLog(@"User started a new line");
     }
     return YES;
}
like image 30
Stuart Campbell Avatar answered Oct 22 '22 01:10

Stuart Campbell