Swift: Let's talk about text (UILabel, CATextLayer, UIView, CoreText, UITextView, UIWebView)



In preparation for a series of posts looking at the presentation of text in iOS, this post describes use cases and an overview of the main options.

There are a number of posts based around text display on this site already, some of which are referenced in this post, but these are mostly older posts written with Objective-C code examples, or only discuss text as part of a larger project. This is something I hope to rectify with the posts that follow this one, but first let's get to know the main options for text display.

UILabel

When programming for iOS, the entry point for most people into the world of text is the UILabel. The UILabel can be conveniently dragged and dropped onto a view inside a Storyboard file and does many of the things that are needed for the display of a small amount of text.

The UILabel class is extremely flexible once tamed. It is capable of displaying text across single or multiple lines, text can be wrapped and/or truncated, as well as being styled (using NSAttributedStrings).

As well as the flexibility bestowed on a UILabel in its own right, it is also a subclass of UIView, which in turn is a subclass of UIResponder. This makes it possible to not only position, colour, mask and access the underlying layer of a UILabel, among other things, but to also receive touch information.

CATextLayer

A CATextLayer is capable of performing a similar role to a UILabel, but without the benefits of inheritance from UIView and UIResponder. It has a simple line of inheritance from CALayer and, in turn, NSObject.

If your main concern is to visually present and perhaps animate, or transform text within three-dimensional space, then a CATextLayer cuts through all the unnecessary elements of a UILabel, and lets you get straight to the graphical manipulation of attributed text without unnecessary complexity.

UIView

It's possible to write text directly onto a view using CoreText. As demonstrated in this earlier blogpost.

At your disposal is a whole array of "opaque types" that enable text to be drawn. CTFramesetter handles multiline frames of text, which in turn utilises a CTTypesetter instance for setting the CTLine instances, which in turn is composed of an array of CTRun instances.

At each point along the chain instances can be probed and manually instantiated (with the exception of CTRuns). But the complexity, which makes CoreText so flexible, also makes it a challenge to initially learn.

UITextView

UITextView underwent great improvements in iOS 6 and 7 placing it firmly in between the more complex option of CoreText, and the easy (but less than satisfactory) option of UIWebView. It removes the hassles of working with drawRect when displaying large amounts of text, and while an instance can stand alone, the class comes into its own when combined with NSTextStorage, NSLayoutManager and NSTextContainer as described in this earlier (pre-Swift) blogpost.

The class comes with the same benefits of inheritance as UILabel (i.e. from UIView, UIResponder and NSObject) but adds to this by also being a descendant of UIScrollView.

UIWebView

One of the easiest options for displaying whole pages of text in the early days of iOS was the UIWebView. Not only could drawing direct to a view be avoided, but the benefit of using HTML escaped the need to get involved with NSAttributedStrings.

These days NSAttributedStrings can be instantiated using HTML and RTF on iOS, while the benefits of a UITextView and its accompanying classes mean that we needn't suffer the loading delays of a UIWebView and can instead enjoy the luxuries of better text presentation.

I'd no longer recommend UIWebView for the display of text and instead would encourage programmers to adopt one of the other available classes (or types) for greater speed and flexibility.


Endorse on Coderwall

Comments

  1. I tried to use NSAttributedString instantiated with HTML, but when I have more labels on the screen with that attributed string, presenting this screen is too slow and takes too much time. It's my experience.

    ReplyDelete
    Replies
    1. Deny, thanks for this observation. Out of interest, is the HTML lengthy or does it have a complex number of tags?

      Delete
    2. I have 4 labels on the screen, 3 of them contains simple short string with bold tags, one is simple short string with hyperlink tag. So I don't know, why it is too slow.

      Delete
    3. It's probably the hyperlink causing your issues. Apple's documentation states: "Calling [this method] from the main thread works (but can still time out if the HTML contains references to external resources, which should be avoided at all costs). The HTML import mechanism is meant for implementing something like markdown (that is, text styles, colors, and so on), not for general HTML import."

      Delete
    4. It's hyperlink, not external resource, nothing is downloaded, but link for external website is created. I tried remove this hyperlink, but speed not change.

      Delete
    5. My mistake. I'll keep an eye out for this and see if I can find any reason it might happen.

      Delete

Post a Comment