Built on top of the Core Text framework sits Text Kit, a high-level text layout and rendering API in iOS 7. Text Kit makes text much easier to work with than having to drop down to Core Text. It allows you to implement rich, text-based applications such as magazine readers or document editors that often require custom text styles and layouts. Features such as these were possible prior to iOS 7, but required complex implementations. However, with Text Kit, they are a breeze to create:
Text Kit’s architecture separates text storage from layout and display as illustrated below:
- NSTextContainer – Provides the coordinate system and geometry that is used to layout text.
- NSLayoutManager – Lays out text by turning text into glyphs.
- NSTextStorage – Holds the text data, as well as handles batch text property updates.
These three classes are applied to a view that renders text. The built-in text handling views, such as UITextView, UITextField, and UILabel already have them set, but you can create and apply them to any UIView instance as well.
The NSTextStorage instance communicates any changes to the text – such as changes to characters or their attributes – to the layout manager for display. NSTextStorage inherits from NSMutableAttributedString, allowing changes to text attributes to be specified in batches between BeginEditing and EndEditing calls.
For example, the following code snippet specifies a change to the foreground and background colors, respectively, and targets particular ranges:
textView.TextStorage.BeginEditing (); textView.TextStorage.AddAttribute(UIStringAttributeKey.ForegroundColor, UIColor.Green, new NSRange(200, 400)); textView.TextStorage.AddAttribute(UIStringAttributeKey.BackgroundColor, UIColor.Black, new NSRange(210, 300)); textView.TextStorage.EndEditing ();
After EndEditing is called, the changes are sent to the layout manager, which in turn performs any necessary layout and rendering calculations for the text to be displayed in the view, as shown:
In addition to manipulating text attributes, Text Kit also makes it easy to control layout. This simplifies the once difficult process of creating custom text layouts, making it easier to implement.
For example, we can create multiple text containers for the layout manager to use for a multi-column layout by following a few easy steps:
- Create a text storage instance
- Create a layout manager
- Add the layout manager to the text storage
- Create a text container
- Add the text container to the layout manager
- Create a text view with the text container
- Repeat steps 4 – 6 for an additional column
var storage = new NSTextStorage (); NSDictionary options = null; NSError error = null; storage.ReadFromFile (NSUrl.FromFilename ("Text.txt"), new NSDictionary (), ref options, ref error);
var layoutManager = new NSLayoutManager ();
storage.AddLayoutManager (layoutManager);
var leftContainer = new NSTextContainer (size);
layoutManager.AddTextContainer (leftContainer);
var leftColumn = new UITextView ( new RectangleF (new PointF (padding, padding), size), leftContainer); leftColumn.AutoresizingMask = UIViewAutoresizing.All; leftColumn.ScrollEnabled = false; View.Add (leftColumn);
// create another text container var rightContainer = new NSTextContainer (size); // add second text container to layout manager layoutManager.AddTextContainer (rightContainer); // init text view with second text container var rightColumn = new UITextView ( new RectangleF (new PointF (padding * 2 + size.Width, padding), size), rightContainer); rightColumn.AutoresizingMask = UIViewAutoresizing.All; View.Add (rightColumn);
With the layout containers defining the area to draw the text for each text view, we get a nice 2 column text layout as shown below:
As you can see, having Text Kit now makes creating text-based features much more approachable than in the past. You can download the code from this post here to give it a try and see what interesting text scenarios you can come up with.