Get Started With JSConstraints - Programmatic Swift Constraints for Beginners
Tags: swift, autolayout, xcode
Published: 2022-03-10 11:06:15

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s28z4tehp5rtcjxk59ln.png)
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y6qeekcf75ywrlndkuzn.jpeg)

Well well, let me introduce you to **[JSConstraints](https://github.com/jaysack/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 
```swift
pod init
```
**Installation**
It can be installed using [cocoapods](https://cocoapods.org/) (which we are going to use) or [swift package manager](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app)
**Using cocoapods**
Open `Podfile` and add 
```swift
pod 'JSConstraints'
```
Save your file and install pods with
```swift
pod install
```
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.

``` swift
let firstView = UIView()
```
![It's that simple to use JSConstraints](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kr7e717dt7q96ohvgsuq.jpeg)

**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
```swift
import JSConstraints
```
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](https://github.com/jaysack/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
```swift
// 1. Create UIView
let firstView = UIView()

// 2. Give it a background color
firstView.backgroundColor = .blue
```
Using `pinTo` method, let's add our view to the parent view with a padding of 20.
```swift
// 3. Pin it to its parent view
firstView.pinTo(superview: view, padding: 20)
```
Build and run (cmd+r) your project and see the magic happen😉.
![first uiview in xcode with JSConstraints pin to method](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/spbtl5jab0oz6pm6hiqq.png)
We have just pinned our child view to our parent view.
You can still customize the padding sizes for each side using `pinTo`.
```swift
// 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)
```

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:
```swift
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>)
])
```
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](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/index.html) 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
```swift
// 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)
])
```
Build and run (cmd+r) your project
![JSConstraints auto layout](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lxk0y1l3lzg4lty0ea1a.png)
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,
```swift
firstView.setConstraints([
   .top(view.topAnchor) + .constant(20),
   .leading(view.leadingAnchor) + .constant(20),
   .bottom(view.bottomAnchor) + .constant(20),
   .trailing(view.trailingAnchor) + .constant(20)
])
```
![JSConstraints autolayout padding](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5knsiqatnt6i2ea9bicn.png)
Now our parent view is visible in white👏🏿.
![A lot JSConstraints auto layout](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/feiht3ar94b8opyfpfgt.gif)

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
```swift
// 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)
```
After adding our square view to the parent view, then we give it a frame using our `setConstraints` method.
```swift
// 4. apply constraints to our view
squareVIew.setConstraints([
     .top(view.topAnchor) + .constant(50),
     .leading(view.leadingAnchor) + .constant(50),
     .squared(200)   // <---- Our focus
])
```
Build and run your project.
![JSConstraints squared enum](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/erk7cxf8k7gf0spwzhfc.png)
In this case `.squared(200)` is equivalent to
```swift
squareVIew.setConstraints([
    .height(200),
    .width(200)
])
```
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.
```swift
// Positioning squareView at the center of our parent view
squareView.centerIn(superview: view)
```
Let's the result of our method

![Centering a uiview with JSConstraint CenterIn](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cz5mwo94zhnm4g0k8drz.png)
What if you want to offset the center position!
```swift
// CenterIn with offset parameters
squareView.centerIn(superview: view, xOffset: <CGFloat>, yOffset: <CGFloat>)
```

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hdwe1lu3pt9zzbnwfail.gif)

### 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_.
```swift
// Initialising setDefaultConfig
stackView.setDefaultConfig(spacing: <CGFloat>, axis: <NSLayoutConstraint.Axis>, alignment: <UIStackView.Alignment>, distribution: <UIStackView.Distribution)
```
- 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.
```swift
// 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)
```
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.
```swift
let redView = UIView()
let blueView = UIView()
let stackView = UIStackView()
```
Give the views background colors to differentiate them.
```swift
redView.backgroundColor = .systemRed
blueView.backgroundColor = .systemBlue
```
Attach the stackView to parent view.
```swift
view.addSubview(stackView)
```
Add redView and blueView to stackView using `addArrangedView`.
```swift
stackView.addArrangedSubview(redView)
stackView.addArrangedSubview(blueView)
```
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.
```swift
stackView.setDefaultConfig(spacing: 40, axis: .horizontal, alignment: .fill, distribution: .fillEqually)
```
Add padding to stack view child views by using `setEdgeInsets`. You can take different approaches as discussed. Let's use the first one.
```swift
stackView.setEdgeInsets(padding: 10)
```
After configuring the child views, now let's pin our stack view to the main view.
```swift
stackView.setConstraints([
    .top(view.topAnchor),
    .leading(view.leadingAnchor),
    .trailing(view.trailingAnchor),
    .height(200)
])
```
Now let's see the results
![JSConstraints stackview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/84z10okmvqr4mfyzfxq9.png)

![easy peasy JSConstraints](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xp8330hnjhaxfqgvhd5g.gif)

### 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.