DEV Community

Cover image for Get Started With JSConstraints - Programmatic Swift Constraints for Beginners
nshutinicolas
nshutinicolas

Posted on • Edited on

Get Started With JSConstraints - Programmatic Swift Constraints for Beginners

Storyboards in Xcode have always been the first must learn way of building UIs and whoever came with this idea is a genius💪🏿. As you develop more apps, you get to learn pros and cons of storyboards.
Today we are going to put storyboards aside and concentrate on writing everything programmatically.
Auto layout constraints is a statement you can’t avoid where Constraints basically define the relationship between our views in the user interface.

If you have used Xcode to create an app and wrote views programmatically, there is a 99% chance that you have come across something similar to this.
Autolayout constraints with NSLayoutConstraints
That looks fine until the project gets bigger.

What if I tell you that the six lines you see (from 24 to 30) can be reduced to a single line.
shocking JSConstraints move

Well well, let me introduce you to JSConstraints

It is a tiny Swift library written with only one thing in mind: Blazin' Fast Programmatic Constraints-Typing.
JSConstraints is a really small library extending UIView and UIStackView functionalities.

Prerequisites

  • Xcode installed on your machine
  • Zeal to learn

Getting started
Create an Xcode project, let's say JSConstraintsTutorial and don’t forget to choose Storyboard as your interface.

Initiate pods for your newly created project

pod init
Enter fullscreen mode Exit fullscreen mode

Installation
It can be installed using cocoapods (which we are going to use) or swift package manager
Using cocoapods
Open Podfile and add

pod 'JSConstraints'
Enter fullscreen mode Exit fullscreen mode

Save your file and install pods with

pod install
Enter fullscreen mode Exit fullscreen mode

Open your project’s JSContraintsTutorial.xcworkspace and start getting your hands dirty.

Creating UIViews programmatically
There are many tutorial that can help you get started and here, we shall do the basics.
Creating a UIView is pretty simple and straightforward.

let firstView = UIView()
Enter fullscreen mode Exit fullscreen mode

It's that simple to use JSConstraints

Import library
To use the library, you will have to import it. You can copy and paste the line of code at the top of your file

import JSConstraints
Enter fullscreen mode Exit fullscreen mode

If that is done, then we can now start exploiting its methods.

Positioning your view

Views in Xcode are positioned relative to other views. Take an example of you trying to paint something, there has to be a material to paint on and that material is the parent view while the image you are painting is a child view.
To position the image, you have to define the distance from top, left, bottom, right or width and height.
For the web gulus, you are probably well oriented with the concept of padding and for others it is a way of creating space around an element.
Look at it in a sense of you seated on a chair, the distance between you and the edge of the chair is the padding.
For now we are talking about the distance of a child view from the edges of it’s parent view.

JSConstraints provides us with methods that are easy to use to achieve this.

PinTo
It is a method that is applied to a child view to position it in it's parent view just like you pin a poster on your wall.

Pin to superview with padding

In your viewDidLoad function, create your first view and give it a background color

// 1. Create UIView
let firstView = UIView()

// 2. Give it a background color
firstView.backgroundColor = .blue
Enter fullscreen mode Exit fullscreen mode

Using pinTo method, let's add our view to the parent view with a padding of 20.

// 3. Pin it to its parent view
firstView.pinTo(superview: view, padding: 20)
Enter fullscreen mode Exit fullscreen mode

Build and run (cmd+r) your project and see the magic happen😉.
first uiview in xcode with JSConstraints pin to method
We have just pinned our child view to our parent view.
You can still customize the padding sizes for each side using pinTo.

// Method 1: padding applies to both x and y sides
firstView.pinTo(superview: view, padding: 20)

// Method 2: you specify the padding for each side individually
firstView.pinTo(superview: view, xPadding: 20, yPadding: 20)
Enter fullscreen mode Exit fullscreen mode

I know you are probably feeling like an expert which you are right now.
Huhh! Wait until you get the next concept that will build a spaceship equivalent of the best app layout you can think about.

SetConstraints

This is a game changing method that let's you resize your views, position them relative to each other with one principal of keeping the code easy to read.
It takes in an array of constraints and returns an activated array of constraints.
Constraints allow us to create views that dynamically adjust to different size classes and positions.
The most commonly used are:

view.setConstraints([
    .top(<NSLayoutAnchor<NSLayoutYAxisAnchor>>),
    .leading(<NSLayoutAnchor<NSLayoutXAxisAnchor>>),
    .trailing(<NSLayoutAnchor<NSLayoutXAxisAnchor>>),
    .bottom(<NSLayoutAnchor<NSLayoutYAxisAnchor>>),
    .height(<CGFloat>),
    .width(<CGFloat>),
    .xCenter(<NSLayoutAnchor<NSLayoutXAxisAnchor>>),
    .yCenter(<NSLayoutAnchor<NSLayoutYAxisAnchor>>),
    .squared(<CGFloat>)
])
Enter fullscreen mode Exit fullscreen mode

Let's start with the positioning of the view like we did earlier.
Here I'm assuming you already have basic knowledge about Auto layout and if you don't, worry not and keep reading and you will eventually understand the concept.
From our previous code, we are replacing our pinTo method with

// 3. Add child view to parent view as a subview
view.addSubview(firstView)

// 4. apply setConstraints to our view
firstView.setConstraints([
   .top(view.topAnchor),
   .leading(view.leadingAnchor),
   .bottom(view.bottomAnchor),
   .trailing(view.trailingAnchor)
])
Enter fullscreen mode Exit fullscreen mode

Build and run (cmd+r) your project
JSConstraints auto layout
What we have just done is to wrap the whole child view over the parent view and that is why you can't see the white parent view.
What if we want our padding back!
Well rest your worries as JSConstraints has .constant() that takes in a CGFloat (fancy way of defining a float value in swift) value and is appended to some of the elements above.
If I wanted to add padding to the top, left, bottom and the right side, update your code to have,

firstView.setConstraints([
   .top(view.topAnchor) + .constant(20),
   .leading(view.leadingAnchor) + .constant(20),
   .bottom(view.bottomAnchor) + .constant(20),
   .trailing(view.trailingAnchor) + .constant(20)
])
Enter fullscreen mode Exit fullscreen mode

JSConstraints autolayout padding
Now our parent view is visible in white👏🏿.
A lot JSConstraints auto layout

Let's talk more about .squared() that combines .height() and .width().
As we have done before, we are going to instantiate our square view, with a yellow background and add it to our parent view

// 1. Instantiate your view
let squareVIew = UIView()

// 2. Give it a background color
squareVIew.backgroundColor = .systemYellow

// 3. Add it to the parent view
view.addSubview(squareVIew)
Enter fullscreen mode Exit fullscreen mode

After adding our square view to the parent view, then we give it a frame using our setConstraints method.

// 4. apply constraints to our view
squareVIew.setConstraints([
     .top(view.topAnchor) + .constant(50),
     .leading(view.leadingAnchor) + .constant(50),
     .squared(200)   // <---- Our focus
])
Enter fullscreen mode Exit fullscreen mode

Build and run your project.
JSConstraints squared enum
In this case .squared(200) is equivalent to

squareVIew.setConstraints([
    .height(200),
    .width(200)
])
Enter fullscreen mode Exit fullscreen mode

What if we want to position our squareView at the center of the parent view!

CenterIn

It is another method that positions a view at the center of it's parent view.

// Positioning squareView at the center of our parent view
squareView.centerIn(superview: view)
Enter fullscreen mode Exit fullscreen mode

Let's the result of our method

Centering a uiview with JSConstraint CenterIn
What if you want to offset the center position!

// CenterIn with offset parameters
squareView.centerIn(superview: view, xOffset: <CGFloat>, yOffset: <CGFloat>)
Enter fullscreen mode Exit fullscreen mode

If you have managed to reach here, then grab a cup of coffee and appreciate what you’ve learnt as you prepare to read on for the next mind blowing concept.
Mind blowing JSConstraits swift

UIStackView

This is a very powerful component that stacks views together either vertically or horizontally.
It is the most preferred way of building UI since it creates most of the constraints automatically.
Creating a UIStackView can’t get any simpler with the JSConstraint library.

JSConstraints comes with two powerful methods

  • setDefaultConfig: Helps to configure stack view subviews layout. It takes in spacing between view, axis which can be either horizontal or vertical, alignment and distribution.
// Initialising setDefaultConfig
stackView.setDefaultConfig(spacing: <CGFloat>, axis: <NSLayoutConstraint.Axis>, alignment: <UIStackView.Alignment>, distribution: <UIStackView.Distribution)
Enter fullscreen mode Exit fullscreen mode
  • setEdgeInsets: adds padding to stack view and its child views. You can specify the padding that applies to sides or x and y side or each side be given it’s value. Example of how it can be used.
// 1. Padding applies to all sides
stackView.setEdgeInsets(padding: 10)

// 2. Specify the x and y values
stackView.setEdgeInsets(x: 10, y: 10)

// 3. Specify the value for each side
stackView.setEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10)
Enter fullscreen mode Exit fullscreen mode

We learn by example. Let's stack two views together in a stackView and explain how it was done.

Instantiate the stackView and two UIViews namely redView and blueView.

let redView = UIView()
let blueView = UIView()
let stackView = UIStackView()
Enter fullscreen mode Exit fullscreen mode

Give the views background colors to differentiate them.

redView.backgroundColor = .systemRed
blueView.backgroundColor = .systemBlue
Enter fullscreen mode Exit fullscreen mode

Attach the stackView to parent view.

view.addSubview(stackView)
Enter fullscreen mode Exit fullscreen mode

Add redView and blueView to stackView using addArrangedView.

stackView.addArrangedSubview(redView)
stackView.addArrangedSubview(blueView)
Enter fullscreen mode Exit fullscreen mode

Now we are applying the knowledge we have acquired about setDefaultConfig to arrange redView and blueView horizontally with spacing of 40 and allow them to fill equally.

stackView.setDefaultConfig(spacing: 40, axis: .horizontal, alignment: .fill, distribution: .fillEqually)
Enter fullscreen mode Exit fullscreen mode

Add padding to stack view child views by using setEdgeInsets. You can take different approaches as discussed. Let's use the first one.

stackView.setEdgeInsets(padding: 10)
Enter fullscreen mode Exit fullscreen mode

After configuring the child views, now let's pin our stack view to the main view.

stackView.setConstraints([
    .top(view.topAnchor),
    .leading(view.leadingAnchor),
    .trailing(view.trailingAnchor),
    .height(200)
])
Enter fullscreen mode Exit fullscreen mode

Now let's see the results
JSConstraints stackview

easy peasy JSConstraints

Conclusion

JSConstaints not only works with blocks, it can also be applied to UITextField, UITextView, ImageView and basically every element that inherits from UIView in Xcode.

Top comments (0)