0

I have this editable text view inside a table view cell, maximumNumberOfLines is set to 4 and lineBreakMode to byClipping. This works pretty much as intended, however it seems you can type past the width of the text view, like so:

Infinite typing

Although the characters are not visible they are being stored somewhere, because in order to get back to visible text, deleting as much as you typed outside the bounds is necessary.

I am struggling to find something unique about these invisible characters, so that a simple deleteBackward() does the job inside an if statement. This way, the user cannot physically type past the bounds of the text view.

What is something about these invisible characters I can identify in textView:shouldChangeTextIn, so I deleteBackwards() and invalidate the type?

rodrigochousal
  • 401
  • 4
  • 19
  • Try converting the solution posted here to swift: http://stackoverflow.com/questions/21889657/uitextviews-text-going-beyond-bounds – AnthonyW Dec 21 '16 at 17:46

2 Answers2

0

Place this in your UITextViewDelegate:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if text.isEmpty { // Always allow backspace
        return true
    }
        let numLines: Int = Int(textView.contentSize.height/textView.font!.lineHeight);
        return numLines <= 4
    }

Would be best to swap out that hardcoded 4 for a nice constant or something.

Note: This may allow 1 extra character on the "fifth" line. To avoid this you would need to add extra code to anticipate what the content size would be and respond accordingly.

AnthonyW
  • 1,910
  • 5
  • 25
  • 46
  • Thanks, but this is actually not what I was looking for. There was no problem with the maximum amount of lines, as the table view's `maximumNumberOfLines` constant was set earlier and was working. The problem was in an overflow of text in the horizontal direction, not the vertical. – rodrigochousal Dec 21 '16 at 13:28
  • I have done some testing and looked at other solutions on SO. This limits the extra characters to 1. Other solutions will let you keep typing off the screen. If the implementation of `UITextView` was not hidden, there would be a much easier solve. – AnthonyW Dec 21 '16 at 17:05
0

I found the caretRect width for the text view when text overflowed was slightly wider than all other previous lines when text overflowed. This was unlike both contentSize and textView.frame.size, which did not change when letters overflowed. This allowed me to recognize the overflow and delete the character in question. Here is the full implementation:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {

    let textRect = textView.caretRect(for: textView.endOfDocument)

    //Maximum length of a character is about 10
    if textView.contentSize.width - textRect.maxX < 10 {

        // If user is already deleting, don't delete twice
        if text != "" {
            textView.deleteBackward() // return false works too
        }
    }

    return true
}
rodrigochousal
  • 401
  • 4
  • 19