Creating UIViews Programmatically in Swift
By: Xiomara Figueroa
Tags: Swift, iOS, Autolayout

What to expect

Understanding an iOS screen

View Hierarchy

When to build views programmatically

How to organize your code (MVC Pattern)

Building custom classes (UIView)

An example — the Twitter iOS app

!Massive View Controllers

Setting our constraints (PureLayout)

Understanding an iOS screen

Any iOS app has a many views. Those views needs four values specified in order to be displayed: x, y, width, height.

There are three different ways of building these views: Storyboards, Nib files and Programmatically.

There is a framework in the iOS sdk (UIKit) that includes a set of standard subclasses that range from simple buttons to complex tables among a lot of other view objects. For example, a UILabel object draws a text string and a UIImageView object draws an image.

Views can embed other views and create sophisticated visual hierarchies. This creates a parent-child relationship between the view being embedded (known as the subview) and the parent view doing the embedding (known as the superview).

View Hierarchy

View Hierarchy

The organization of your views influences both the visual appearance of your application and how your application responds to changes and events. For example, the parent-child relationships in the view hierarchy determine which objects might handle a specific touch event. Similarly, parent-child relationships define how each view responds to interface orientation changes.

When to build views programmatically

It’s often a good call to use custom code when you have:

Dynamic layouts

Views with effects, rounded corners, shadows, etc.

Any case in which using Storyboards is complicated.

How to organize your code (MVC Pattern)

Model-View-Controller is possibly the most used design pattern of all. When starting with iOS development it’s common to run into The Massive View Controller problem: The View Controllers often become too big, containing all sort of functionality that becomes really hard to modify or refactor.

By follow this pattern we ensure that each class in our project is either a Controller, a Model or a View. That’ll make it easier to create all our views programmatically without creating a spaghetti monster. Obviously we can have other groups and classes, but the core of the application is contained in these three categories.

Getting Started

When starting a new project, Xcode initialize it with a storyboard. In order to create our custom views we need to discard the storyboard.

Next, create two files: ProfileView as a UIView class under the View category and ProfileViewController as a UIViewController class under the Controller category.

Auto Layout

Auto Layout will determine the frame for each view in your screen, so each view should have a constraint that will help determine it’s width, height, x and y positions. Writing Auto Layout code from scratch isn’t easy — PureLayout provides a fully capable and developer friendly interface for Auto Layout.

Before we go on, let’s add PureLayout to our project. There are various ways to add PureLayout to your Swift project. I’m using cocoapods, a dependency manager for Swift and Objective-C projects. It requires a file named Podfile that looks like this:

Next run the following command to install dependencies, PureLayout in this case:

pod install

This command will create a new project file that ends in .xcworkspace. For now on, this is the file we’ll open in Xcode to continue developing the app.

Building custom classes

In our ProfileView.swift file you’ll see the template of a UIView class implementation that looks like this:

import UIKit class ProfileView: UIView { }

We need to initialize our class. Initializers are a big deal in Swift, you can read more about it here if you want to. For now all you need to know is that there are primary initializers, which are responsible for initializing all properties of a class. Here’s an example of a typical implementation:

Since we are adding constraints in a UIView subclass, we should override the updateConstraints method. This method may be called more than once during the lifetime of the object. To avoid duplicate constraints you should keep a flag (shouldSetupContraints) that lets you know once you have done your initial constraint setup. We must call super at the end of the implementation. (You may get a crash if you call super before you change constraints)

Example

Let’s say we want to recreate the profile view of the Twitter iOS app. In the image below, you can see a header view with a banner image, profile image, user info etc. At the bottom of the screen is the table with all the tweets and a tab bar. All the elements marked with purple are subclasses of UIView (UIButtons, UILabels, UIImageViews etc). We are going to focus on the header view, framed in orange in the image below.

More specifically, we are going to take out just these three elements in the image below to illustrate our example. The banner and profile images are UIImageViews , and the buttons section is a UISegmentedControl .

First, we need to declare the three objects in our ProfileView class: bannerView , profileView and segmentedControl .

Then, in the init: method we set the properties for each object: background color, border color, and basically the whole appearance setup. Each object needs to be initialized first. Initialize them all with frame equal to zero — Auto Layout will take care of it later.

To add each object’s subview to our view (ProfileView), we use the addSubview: method. This places the specified view on top of other views. The whole thing will look like this:

Setting our constraints (PureLayout)

Layout constraints

Layout constraints are descriptions of the properties and relations between views. The NSLayoutConstraint class is used to create constraints.

There are several types of constraints:

size constraints — an image should have a width of 200px

alignment constraints — a label should be centered vertically on the screen

spacing constraints — space between two objects

Attributes

PureLayout defines view attributes that are used to create auto layout constraints. Some of them are illustrated in this diagram:

Start pinning things!

We have basically thrown three rectangles onto our screen. Now we need to arrange them to look like our Twitter profile:

!Massive View Controllers

We’ve finished our ProfileView, now we call it from our Controller ( ProfileViewController ). Xcode has already created a controller template with the viewDidLoad: method. This is the method that gets called once before presenting the controller. At this point we create an instance of our profileView, as shown below. That should be it!

(Disclaimer: the code presented here is used mainly for illustrative purposes of explaining auto layout. You may need to add other lines in other places to finish a fully-functional project)