Creating UIViews Constraints Programmatically Using PureLayout
Tags: swift, ios, mobile
Published: 2017-12-20 00:57:28

---
title: Creating UIViews Constraints Programmatically Using PureLayout
published: true
description: A Swift 4 tutorial for how to create constraints programmatically without storyboards or NIBs.
tags: Swift, iOS, mobile
cover_image: https://thepracticaldev.s3.amazonaws.com/i/ug6zbzux7wh1msazr9ww.jpg
canonical_url: https://blog.instabug.com/2017/12/nslayoutconstraint-programmatically/
---

####Written by <a href="https://dev.to/alyakan">Aly Yakan</a>

Today, we’ll walk you through <a href="https://blog.instabug.com/2017/12/nslayoutconstraint-programmatically/?utm_source=devto&utm_medium=referral&utm_content=nslayoutconstraint">creating constraints programmatically</a> -- building a simple mobile application’s UI completely in code without the use of Storyboards or NIBs. I will not go into the debate of which is better because, simply, they all have their pros and cons, so I’ll just leave this link here which dives more into that matter: https://www.toptal.com/ios/ios-user-interfaces-storyboards-vs-nibs-vs-custom-code.


###Overview
 

This tutorial was written using Xcode 9 and Swift 4. I also assume that you’re familiar with Xcode, Swift, and CocoaPods.

Without further delay, let’s start building our project: a simple Contact Card application. This tutorial aims to teach you how to build your application’s UI in code, and as such, it will not contain any logic about the application’s functionality unless it serves this tutorial’s purpose.


###Setting up the project
 

Start by firing up Xcode -> “Create a New Xcode Project”. Select “Single View App” and press “Next”.

 

<img src="https://i2.wp.com/blog.instabug.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-22-at-5.31.15-PM.png?w=2400&ssl=1" alt="create constraints programmatically">

 

Name the project anything you’d like, I chose to call it “ContactCard”, for no obvious reasons. Untick all three options below and, of course, choose Swift to be the programming language, then press “Next”.

 

<img src="https://i1.wp.com/blog.instabug.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-22-at-5.31.53-PM.png?w=2400&ssl=1" alt="create constraints programmatically">

 

Choose a location on your computer to save the project. Uncheck “Create Git Repository on my Mac” and press “Create”.

Since we won’t be using Storyboards, or NIBs for that matter, go ahead and delete “Main.storyboard”, which can be found in the Project Navigator here:

 

<img src="https://i0.wp.com/blog.instabug.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-22-at-5.40.20-PM.png?w=2400&ssl=1" alt="create constraints programmatically">

 

After that, click on the project in the Project Navigator and under the “General” tab find the section that says “Deployment Info” and delete whatever’s written next to “Main Interface”, usually it is the word “Main”. This is what tells Xcode which Storyboard file to load with the application startup, but since we just deleted “Main.storyboard”, leaving this line would crash the app since Xcode would not find the file.

 

<img src="https://i2.wp.com/blog.instabug.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-22-at-5.41.49-PM.png?w=2400&ssl=1" alt="create constraints programmatically">

 

So go ahead and delete the word “Main”.

 

 

###Creating ViewController
 

At this point, if you run the application, a black screen will appear as the application now does not have any source of UI to present for the user, so the next part is where we will provide it with one. Open “AppDelegate.swift” and inside    `application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?)`, insert this snippet of code:

 
```swift
    self.window = UIWindow(frame: UIScreen.main.bounds) 
    let viewController = ViewController() 
    self.window?.rootViewController = viewController    
    self.window?.makeKeyAndVisible()
```

What this does is basically provide a window for the user’s interaction with the application. This window’s view controller is the one provided with the project on creation, which can be found in “ViewController.swift”. Just as a quick test that everything’s working, head to “ViewController.swift” and inside the `viewDidLoad()` method, insert the following line:

 
```swift
    self.view.backgroundColor = .blue
```

Now run the application on your preferred simulator device.

A useful shortcut to navigate between files in Xcode is “⇧⌘O” and then typing the file’s name or even a piece of code that you’re looking for and a list of files will come up on the screen from which you can choose.

After running the application, this should be the result on your simulator’s screen:

 

<img src="https://i0.wp.com/blog.instabug.com/wp-content/uploads/2017/10/Simulator-Screen-Shot-iPhone-7-2017-10-22-at-18.26.00.png?w=638&ssl=1" width="500" alt="create constraints programmatically" class="aligncenter" >

 

Of course we won’t use that hideous blue so just turn the background back to white by replacing `.blue` with `.white` inside `viewDidLoad()`.

 

 

###Laying out the UI
 

For laying out our UI, we’ll be using a very helpful library that will make our lives so much easier. Its repo can be found at https://github.com/PureLayout/PureLayout. To install PureLayout, you should first open up your terminal and “cd” into the project’s directory. You can do this by typing `cd`, then a space, then drag and drop your project’s folder into the terminal and press “Enter”. Now run the following commands inside the terminal:

`pod init`
`pod install`

This should be the output of your terminal after running the second command:

 

<img src="https://i1.wp.com/blog.instabug.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-22-at-6.34.32-PM.png?w=2400&ssl=1" alt="create constraints programmatically">

 

After that, close Xcode, open the folder inside Finder, and you should find something called “<Your Project Name>.xcworkspace”. This is what we’ll be opening to access our application if we ever need to use CocoaPods. Now locate a file called “PodFile” and write the following line under the phrase `use_frameworks!`

 

`pod “PureLayout”`
 

Run pod install in your terminal again and then build your project by pressing “Command + B”.

 

 

###Coffee break
 

Now that everything is set up, let’s start with the real work. Head over to “ViewController.swift” and grab a cup of coffee because here’s what the final result will look like:

 

<img src="https://thepracticaldev.s3.amazonaws.com/i/plomvfzwebnz62jf2qcp.png" width="500" alt="create constraints programmatically" class="aligncenter" >

 

 

###Creating an ImageView
 

Insert the line `import PureLayout` underneath `import UIKit` to be able to use the library in this file. Next, underneath the class declaration and outside of any function, we’ll start by creating the `Avatar ImageView` lazy variable as follows with this snippet of code:

 

```swift
lazy var avatar: UIImageView = {
    let imageView = UIImageView(image: UIImage(named: "avatar.jpg"))
    imageView.autoSetDimensions(to: CGSize(width: 128.0, height: 128.0))
    imageView.layer.borderWidth = 3.0
    imageView.layer.borderColor = UIColor.lightGray.cgColor
    imageView.layer.cornerRadius = 64.0
    imageView.clipsToBounds = true
    return imageView
}()
``` 

As for the image, get any image on your desktop that you’d like to use as an avatar, draw and drop it in Xcode under <Your Project’s Name> folder, which in my case is “ContactCard”, and check on “Copy items if needed”.

 

<img src="https://i0.wp.com/blog.instabug.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-23-at-10.06.50-PM.png?w=2400&ssl=1" alt="create constraints programmatically">

 

Then click “Finish”. After that, write that file’s name along with its extension inside the declaration of the `UIImage` instead of “avatar.jpg”.

For those of you who don’t know, lazy variables are like normal variables except they do not get initialized (or allocated any memory space) until they are needed, or being called, for the first time. This means that lazy variables don’t get initialized when the view controller is initialized, but rather they wait until a later point when they are actually needed, which saves processing power and memory space for other processes. These are especially useful in the case of initializing UI components.

 

 

###PureLayout in action
 

As you can see inside the initialization, this line `imageView.autoSetDimensions(to: CGSize(width: 128.0, height: 128.0))` is PureLayout in action. With just a single line, we set a constraint for both the height and width of the `UIImageView` and all the necessary `NSLayoutConstraint` lines are created without the hassle of dealing with their huge function calls. If you’ve dealt with creating constraints programmatically, then you must have fallen in love by now with this brilliant library.

To make this image view round, we set its corner radius to half its width, or height, which is 64.0 points. Also, for the image itself to respect the roundness of the image view, we set the `clipsToBounds` property to true, which tells the image that it should clip anything outside the radius that we just set.

We then move to creating a `UIView` that will serve as the upper part of the view behind the avatar which is colored in gray. The following lazy var is a declaration for that view:

 
```swift
lazy var upperView: UIView = {
    let view = UIView()
    view.autoSetDimension(.height, toSize: 128)
    view.backgroundColor = .gray
    return view
}()
```

 

###Adding subviews
 

Before we forget, let’s create a function called `func addSubviews()` that adds the views we just created (and all the other views that we’re going to create) as subviews to the view controller’s view:

 
```swift
func addSubviews() {
    self.view.addSubview(avatar)
    self.view.addSubview(upperView)
}
```

And now add the following line to `viewDidLoad(): self.addSubviews()`

 

 

###Setting up constraints
 

Just to get a picture of how far we are, let’s setup the constraints for these two views. Create another function called func setupConstraints() and insert the following constraints:

 
```swift
func setupConstraints() {
    avatar.autoAlignAxis(toSuperviewAxis: .vertical)
    avatar.autoPinEdge(toSuperviewEdge: .top, withInset: 64.0)
    upperView.autoPinEdge(toSuperviewEdge: .left)
    upperView.autoPinEdge(toSuperviewEdge: .right)
    upperView.autoPinEdgesToSuperviewEdges(with: .zero, excludingEdge: .bottom)
}
```

Now inside `viewDidLoad()` call `setupConstraints()` by adding its function call as follows: `self.setupConstraints()`. Add this AFTER the call to `addSubviews()`. This should be the final output:

 

<img src="https://thepracticaldev.s3.amazonaws.com/i/ob9e1fqa2xotpro2f4u8.png" width="500" alt="create constraints programmatically" class="aligncenter" >

 

 

###Bring to front
 

Oops, that doesn’t seem right. As you can see, our `upperView` lays on top of the `avatar`. This is because we added `avatar` as a subview before `upperView`, and since those subviews are arranged in a stack of some sort, then it is only natural to see this result. To fix this, we can just replace those two lines with each other, but there is also another trick that I want to show you, which is: `self.view.bringSubview(toFront: avatar)`.

This method will bring the avatar all the way from the bottom of the stack right back to the top, no matter how many views there were above it. So choose whichever method you’d like. Of course for readability, it’s better to add the subviews in the order that they should appear above the other, if they would ever happen to intersect, while keeping in mind that the first added subview will be at the bottom of the stack and so any other intersecting view will appear on top of it.

And this is how it should really look like:


<img src="https://thepracticaldev.s3.amazonaws.com/i/vlub2ygvfouxn5o85a6l.png" width="500" alt="create constraints programmatically" class="aligncenter">


 

###Creating segmented control
 

Moving on, we’ll now create the segmented control, which is the gray bar that contains three sections. Creating the segmented control is actually simple. Just do the following:

 
```swift
lazy var segmentedControl: UISegmentedControl = {
    let control = UISegmentedControl(items: ["Personal", "Social", "Resumè"])
    control.autoSetDimension(.height, toSize: 32.0)
    control.selectedSegmentIndex = 0
    control.layer.borderColor = UIColor.gray.cgColor
    control.tintColor = .gray
    return control
}()
```

I believe everything is clear, the only different thing is that upon initialization we provide it with an array of strings, each string representing one of our desired sections’ title. We also set the selectedSegmentIndex to 0, which tells the segmented control to highlight/choose the first segment upon initialization. The rest is just styling which you can play around with.

Now let’s go ahead and add it as a subview by inserting the following line to the end of `func addSubviews(): self.view.addSubview(segmentedControl)` and its constraints will be:

 
```swift
    segmentedControl.autoPinEdge(toSuperviewEdge: .left, withInset: 8.0)
    segmentedControl.autoPinEdge(toSuperviewEdge: .right, withInset: 8.0)
    segmentedControl.autoPinEdge(.top, to: .bottom, of: avatar, withOffset: 16.0)
```

Take a moment to wrap your head around these. We tell the segmented control that we want to pin it to the left side of its superview, however, we want a a little bit of spacing instead of sticking it directly to the edge of the screen. If you notice, I’m using what is called an eight-point grid where all spacings and sizes are a multiple of eight. I do the same to the right side of the segmented control. As for the last constraint, it simply says to pin its top to the bottom of avatar with a spacing of 16 points.

After adding the constraints above to `func setupConstraints()`, run the code and make sure that it looks like the following:

 

<img src="https://thepracticaldev.s3.amazonaws.com/i/htbxlfdnywj4zhegvikr.png" alt="create constraints programmatically" width="500" class="aligncenter" >
 

 

###Adding a button
 

Now comes the last piece of UI for this small tutorial, which is the “Edit” button. Add the following lazy variable:

 
```swift
lazy var editButton: UIButton = {
    let button = UIButton()
    button.setTitle("Edit", for: .normal)
    button.setTitleColor(.gray, for: .normal)
    button.layer.cornerRadius = 4.0
    button.layer.borderColor = UIColor.gray.cgColor
    button.layer.borderWidth = 1.0
    button.tintColor = .gray
    button.backgroundColor = .clear
    button.autoSetDimension(.width, toSize: 96.0)
    button.autoSetDimension(.height, toSize: 32.0)
    return button
}()
```

Don’t be alarmed by how big the initialization is, but pay attention to how I set the title and its color by calling the function button.setTitle and button.setTitleColor. For certain reasons, we cannot set a button’s title by accessing its titleLabel directly and this is because there are different states for a button and many people would find it convenient to have different titles/colors for different states.

Now add the button as a subview like the rest of the components and add the following constraints to have it appear where it is supposed to be:

 
```swift
editButton.autoPinEdge(.top, to: .bottom, of: upperView, withOffset: 16.0)
editButton.autoPinEdge(toSuperviewEdge: .right, withInset: 8.0)
```

Here we only set the right and top constraints for the button, and since we gave it a size, it won’t expand and will need nothing else. Now go ahead and run the project to see the final result:

 

<img class="aligncenter" src="https://thepracticaldev.s3.amazonaws.com/i/22x04slfiupxn7ykgkaa.png" alt="create constraints programmatically" width="500" />



###Some final notes
 

Play around, add as many UI elements as you want. Try to re-create any application’s views that you see challenging. Start simple and build up from there. Try to draw the UI components on a piece of paper so you can imagine how they fit together.



*_Learn more at <a href="https://blog.instabug.com/?utm_source=devto&utm_medium=referral&utm_content=nslayoutconstraint">blog.instabug.com</a>._*