Want to offer native, in-app customer service to your users? Get going quickly with Zendesk’s Mobile SDKs. Free with Zendesk.

Active Filters: Text

Text is a huge part of iOS apps. Today we'll look at one way we can polish up the text in our apps, by allowing it to naturally "flow" around objects. Let's begin.

We'll start with a "before" picture. Here we've got a basic setup with some text and an image in the top right corner. Nothing too fancy here, just a regular UITextView and UIImageView:

let imageView = UIImageView(image: UIImage(named: "steve"))

let textView = UITextView(frame: .zero)  
textView.text = "Here's to the crazy ones..."

This looks fine. But our text is needlessly narrow. It'd be great if we could make the text expand to the full width of the device. We'll change our Text View's layout so it does:

Well, we're getting closer. Now we just need a way to make the text "flow" or "wrap" around our image. We'll start by getting the frame of the image view, then we'll create a path from it:

let imagePath = UIBezierPath(rect: imageView.frame)

Finally, we'll set our new path as one of the exclusionPaths of our Text View's textContainer:

textView.textContainer.exclusionPaths = [imagePath]

Success! Since exclusionPaths is an Array, we can flow text around as many shapes as we want!


#246: UITextField B-sides 📼


UITextField is one of the sort of "low key" hidden gems of UIKit. Today we'll look at some of the lesser-known things it can do and how to configure them. Let's dive in.

We'll begin by creating a text field and customizing its look and feel. First, instead of boring plain placeholder, let's spice things up a bit:

let placeholder = NSMutableAttributedString()

    string: "Spaceship ",
    attributes: [NSFontAttributeName : boldFont]

    string: "Name",
    attributes: [NSFontAttributeName : font]

textField.attributedPlaceholder = placeholder

Nice, now let's customize how our text field works.

Suppose we wanted to clear out its contents when a user tapped it. We simply set clearsOnBeginEditing to true.

Similarly, if we wanted to clear the contents not when the user tapped the field, but rather when the user began typing content, we can set clearsOnInsertion to true.

Let's add some more "padding" to our text field. This turns out to be a tricker than expected.

UITextField allows for customization of the rects it uses to draw text via subclassing:

class PaddedTextField : UITextField {
  override func textRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: 16.0, dy: 8.0)

Finally, we'd like allow users to fancy up (bold, italic, underline) the names of their spaceships. Turns out UITextField makes this super easy:

textField.allowsEditingTextAttributes = true

With attribute editing enabled, we now get this great editing rich-text UI for free. Neat!

Let's draw some strings! There's plenty of text-drawing capabilities in iOS and OS X, with full frameworks like Text Kit (or the lower-level Core Text) dedicated to the task. Today, we'll start looking at these capabilities by using Core Graphics and UIKit to draw a multiline string.

Sometimes we need to draw text ourselves, “manually”. This can be helpful when optimizing for scrolling performance, or when complete customization is necessary.

First we'll need a view to draw into, we'll make a new UIView, and override drawRect.

Next, we'll start implementing our drawRect function with a few variables. We'll choose a font, then setup a paragraph style to make our text multiline, with some tall lines.

We'll also setup some drawing options to tell the system we want multiline text:

let textFont = UIFont(name: "Avenir Next", size: 17.0)!
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineHeightMultiple = 1.2
paragraphStyle.lineBreakMode = .ByWordWrapping

let drawingOptions: NSStringDrawingOptions = [
  .UsesLineFragmentOrigin, .UsesFontLeading]

We'll save these off into a textAttributes dictionary. Next, we'll need to figure out what rectangle we'll be drawing our text into.

We'll use the boundingRectWithSize function to find out how tall it will be when constrained to the width of our view:

let textRect = (text as NSString)
    CGSizeMake(bounds.size.width, CGFloat.max),
    options: drawingOptions,
    attributes: textAttributes,
    context: nil)

Then we'll just pass that calculated textRect into a call to drawWithRect:

(text as NSString).drawWithRect(textRect,
  options: drawingOptions,
  attributes: textAttributes,
  context: nil)


#54: Dynamic Type Basics 📄


Dynamic Type is a system introduced back in iOS 7 with the intention of unifying and simplifying how users change their preference for how big text should be on the screen. While the user choice is simple, under the hood Dynamic Type earns its name by dynamically adjusting things such as spacing between characters and character weights to make text as readable as possible.

Let’s take a look at how to add simple Dynamic Type support.

Text Styles

The main way you interact with Dynamic Type is through the built-in set of text styles. As of iOS 9, 9 styles are available to choose from:

  • UIFontTextStyleTitle1
  • UIFontTextStyleTitle2
  • UIFontTextStyleTitle3
  • UIFontTextStyleHeadline
  • UIFontTextStyleSubheadline
  • UIFontTextStyleBody
  • UIFontTextStyleFootnote
  • UIFontTextStyleCaption1
  • UIFontTextStyleCaption2

Retrieving Fonts

If you’re using the system font, all you need is:


For custom fonts, you’ll need to grab a font descriptor first, then create the UIFont manually:

let fontSize = UIFontDescriptor

let font = UIFont(name: "Avenir Next", size: fontSize)

Lastly, you'll want to update your UI when the user changes their preferences in Settings.app. Observe this notification and trigger a re-layout when it occurs:

  selector: "preferredContentSizeChanged:",
  name: UIContentSizeCategoryDidChangeNotification, object: nil)