Nick Harris

Archive for September 2016

Limiting the Number of Lines in a UITextView

with one comment

Intro

I have a UILabel in my app that shows a maximum 4 lines of text. If the user taps on it, the view becomes editable and the user can change the text in a UITextView.

Problem

I want to limit the user to only 4 lines when they’re editing the text in the UITextView.

First Attempt – Default Behavior

By default a user can add as many lines of text as they want to a UITextView and the view will update itself to make sure the last line is visible.

This is no good for me since the user can enter more lines then I’m going to show when they’re done editing.

Second Attempt – maximumNumberOfLines

According to the docs for NSTextContainer.maximumNumberOfLines:

The layout manager uses the value of this property to determine the maximum number of lines associated with the text container. The default value of this property is 0, which indicates that there is no limit.

In Xcode 8 and iOS 10 the only effect this parameter has on a UITextView is that the last line after the max is no longer made visible. The user can keep entering text all they want but its no longer visible in the UITextView.

My Fix

The fix I came up with was to count the number of line breaks by using CharacterSet.newLines in textView:shouldChangeTextInRange:replacementText: of the UITextViewDelegate before allowing a user change.

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

    let existingLines = textView.text.components(separatedBy: CharacterSet.newlines)
    let newLines = text.components(separatedBy: CharacterSet.newlines)
    let linesAfterChange = existingLines.count + newLines.count - 1

    return linesAfterChange <= textView.textContainer.maximumNumberOfLines
}

This works as intended.

But this feels like a hack around a UIKit bug.

Is it?

Written by Nick Harris

September 11, 2016 at 4:41 am

Posted in Uncategorized