Detecting Truncation in UITextViews

Do your text views show…?

Alex Persian
Dec 10, 2019 · 4 min read
Image for post
Image for post

One of the challenges you might encounter when working with UITextViews is that they don’t provide a straightforward way to detect whether or not they are displaying truncated text.

With a UILabel you can check for truncation by calculating the size of the text within the label and comparing that with the bounds of the label itself. If the text extends beyond the bounds then it’s being displayed as truncated.

The challenge with UITextView is that, by design, it can hold text that is far larger than its bounds.

This is the essence of how a scrolling text view operates. That feature breaks our ability to quickly check for truncation, so to begin with, we need to work with a textview that has scrolling disabled.

Solution

This is where some knowledge on TextKit and how iOS lays out and manipulates rendered text comes in handy. I highly recommend reading up on the TextKit official documentation, along with this excellent write-up by the folks over at objc.io.

From here on, I will assume you have at least a cursory understanding of text layout within iOS.

Since we can’t rely only on the bounds of the UITextView for making this check, we have to lean on the NSLayoutManager within the textview itself.

So, if we have a textview that is displaying truncated text like below then we can use the following snippet to detect that.

Image for post
Image for post
Example of tail truncation

What are we doing here exactly? Well, NSLayoutManager works with line fragments for laying out text. These are essentially rectangles that define the bounds for each line of text.

Again, the objc.io article goes into far more depth than I can here, but the gist is that using that concept of line fragments, we can ask the layout manager to search through them to find the truncation glyph we care about (…).

If it’s found, we can stop the traversal and know that our text is being rendered in a truncated fashion.

Side-note: Why can’t we just search the textContainer.text property for the ... character?

Well, under the hood, the textContainer has no concept of the truncation glyph existing at all. That work is done a layer above by the NSLayoutManager before the text is finally rendered to the screen.

This solution on its own will work great for detecting tail truncation. But what if the textview just isn’t wide enough or tall enough to render all of the text?

For that, we will need to inspect the text container’s characters and glyphs to compare them. An example of such a textview is displayed below, along with the following snippet detailing how the detection works.

Image for post
Image for post
Example of word-wrap truncation

This should now cover both cases where the lineBreakMode is set to byTruncatingTail along with byCharWrapping/byWordWrapping. You can find the full gist of this solution here.

Conclusion

As you can see, it’s not very straightforward to detect whether or not some text is displayed in a truncated fashion. This is likely by design from Apple since it would open up a ton of edge cases, and goes somewhat against the purpose of UITextView.

Even with the solution above, it’s only possible to detect truncation reliably when using the three lineBreakMode settings listed above. It also requires that the textview being inspected has scrolling disabled.

So, use at your own discretion. In my case, the need for this behavior arose from a product requirement where we were displaying shortened comments and we wanted to allow for inline expansion behavior.

Also, I would like to give a huge shoutout to Dave DeLong as he sat with me for a long time to help figure out this solution, and most of the credit for it working properly goes to him.

Anyway, I hope this has helped you out or at least been an informative read. Please leave a comment below if you find an error in my solution or if you have a different approach to this that worked for you. Cheers!

Better Programming

Advice for programmers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store