inaka

Latest blog entries

/
Erlang and Elixir Factory Lite B.A.

A brief introduction about what was the Erlang Factory Conference in Buenos Aires for some Inaka team members

Jul 07 2017 : Euen Lopez

/
The Art of Writing a Blogpost

The Art of Writing a Blogpost

Apr 11 2017 : Matias Vera

/
SpellingCI: No more spelling mistakes in your markdown flies!

Feb 14 2017 : Felipe Ripoll

/
Fast reverse geocoding with offline-geocoder

Do you need a blazing fast reverse geocoder? Enter offline-geocoder!

Jan 18 2017 : Roberto Romero

/
Using Jayme to connect to the new MongooseIM REST services

MongooseIM has RESTful services!! Here I show how you can use them in an iOS application.

Dec 13 2016 : Sergio Abraham

/
20 Questions, or Maybe a Few More

20 Questions, or Maybe a Few More

Nov 16 2016 : Stephanie Goldner

/
The Power of Meeting People

Because conferences and meetups are not just about the technical stuff.

Nov 01 2016 : Pablo Villar

/
Finding the right partner for your app build

Sharing some light on how it is to partner with us.

Oct 27 2016 : Inaka

/
Just Play my Sound

How to easily play a sound in Android

Oct 25 2016 : Giaquinta Emiliano

/
Opening our Guidelines to the World

We're publishing our work guidelines for the world to see.

Oct 13 2016 : Brujo Benavides

/
Using NIFs: the easy way

Using niffy to simplify working with NIFs on Erlang

Oct 05 2016 : Hernan Rivas Acosta

/
Function Naming In Swift 3

How to write clear function signatures, yet expressive, while following Swift 3 API design guidelines.

Sep 16 2016 : Pablo Villar

/
Jenkins automated tests for Rails

How to automatically trigger rails tests with a Jenkins job

Sep 14 2016 : Demian Sciessere

/
Erlang REST Server Stack

A description of our usual stack for building REST servers in Erlang

Sep 06 2016 : Brujo Benavides

/
Replacing JSON when talking to Erlang

Using Erlang's External Term Format

Aug 17 2016 : Hernan Rivas Acosta

/
Gadget + Lewis = Android Lint CI

Integrating our Android linter with Github's pull requests

Aug 04 2016 : Fernando Ramirez and Euen Lopez

/
Passwordless login with phoenix

Introducing how to implement passwordless login with phoenix framework

Jul 27 2016 : Thiago Borges

/
Beam Olympics

Our newest game to test your Beam Skills

Jul 14 2016 : Brujo Benavides

/
Otec

Three Open Source Projects, one App

Jun 28 2016 : Andrés Gerace

/
CredoCI

Running credo checks for elixir code on your github pull requests

Jun 16 2016 : Alejandro Mataloni

/
See all Inaka's blog posts >>

/
iOS Auto Layout

German Azcona wrote this on August 23, 2013 under apple, autolayout, inaka, ios, wwdc .

Apple's WWDC came and went again. And so it’s time for my review of one of the new toys the guys at Cupertino made for us to play with. I am talking about a feature that Mac OS X has had since 2011, a feature that will now be included in iOS 6. I am talking about Auto Layout.

With iOS 5 and previous operating systems, if we wanted to place a visual element on the screen – like views or buttons – we had to add it manually by setting the element’s frame, that is to say, the element's position and size. Position and size became “magic numbers” we either declared in our code or allowed Interface Builder to set on our xib files.

If we want the layout to be consistent when rotating the screen or when changing view sizes, we manually code what we want, or in simple cases, we use the auto-resizing mask properties. The auto-resizing mask allows us to maintain fairly simple layout options for how things stretch and position themselves when the superview is resized.

With these current options we can get the job done, but if the layout requirements get more advanced, it takes some effort to do it and we end up with code that's hard to understand and maintain.

Understanding Auto Layout

Auto Layout is described as a constraint-based descriptive layout system. This means that you describe what you want and the views figure out what their frames should be, which means you no longer have to use those “magic numbers”.

To describe your views, you set constraints. Each constraint is a linear equation. So if you want a control to be in the top middle of its superview, you can describe that as two constraints:

  • Control is a fixed distance from the top of the superview.
  • Control is centered horizontally in its superview.

This can be translated to a linear equation such as:

Control.centerX = Superview.centerX
Control.top = Superview.top + 10

Furthermore, each formula can be abstracted to:

SomeItem.someAttribute = OtherItem.otherAttribute * multiplier + constant

These are the only elements needed to create a constraint. So, in this example:

Control.centerX = Superview.centerX;

The code will be:

<pre><code>
    [NSLayoutConstraint constraintWithItem:<redColor>control</redColor>
        attribute:NSLayoutAttributeCenterX
        relatedBy:NSLayoutRelationEqual
            toItem:<redColor>superview</redColor>
        attribute:NSLayoutAttributeCenterX
        multiplier:1.0
            constant:0.0];
</code></pre>            

And for this example:

Control.top = Superview.top + 10

The code will be:

<pre><code>
    [NSLayoutConstraint constraintWithItem:<redColor>control</redColor>
            attribute:NSLayoutAttributeCenterX
            relatedBy:NSLayoutRelationEqual
                toItem:<redColor>superview</redColor>
            attribute:NSLayoutAttributeTop
            multiplier:1.0
                constant:<redColor>10.0</redColor>];
</code></pre>               

It's interesting to notice that this API allows a relationship parameter to be defined. In this case, it was NSLayoutRelationEqual. However, the constraint’s relationship need not be just equalities. It can also be less than or equal to (<=) or greater than or equal to (>=). This is great for setting maximum and minimum sizes for items.

When comparing constraints with auto-resizing masks, you will notice that constraints allow for more control. They’re much more versatile. Constraints can be applied to any two views regardless of view hierarchy and direction. Auto-resizing masks are only from parent to child, while constraints can be from sibling to sibling, from child to parent, from parent to child, and even between cousin views.

In addition to doing this by programming, you can also set constraints in Interface Builder, which allows for a lot of customization. However, you won’t be able to do all you want with Interface Builder alone.

Visual Format

Now, imagine you want to align two buttons together. You may end up with this code:

<pre><code>
    [NSLayoutConstraint constraintWithItem:<redColor>acceptButton</redColor>
        attribute:NSLayoutAttribute<redColor>Left</redColor>
        relatedBy:NSLayoutRelation<redColor>Equals</redColor>
            toItem:<redColor>cancelButton</redColor>
        attribute:NSLayoutAttribute<redColor>Right</redColor>
        multiplier:1.0
            constant:<redColor>12</redColor>];
</code></pre>          

This code is okay, but it’s a bit confusing – which element ends up to the left and which to the right? Well, Apple also created a visual format syntax capable of dealing with several constraints in a simple way. The following example does the same thing as the previous example:

<pre><code>
    [NSLayoutConstraint constraintsWithVisualFormat:
     @”<redColor>[cancelButton]-(12)-[acceptButton]</redColor>”
        options:0
        metrics:nil
            views:viewsDictionary];
</code></pre>

The viewsDictionary parameter is just a dictionary with the views used on the format string, and options is an alignment mask you can define. Metrics is a dictionary similar to viewsDictionary except that NSNumber replaces the constants used on the format string.

The syntax is powerful and allows a rather big array of options to work with, so I won’t comment on all the options here. I will say, though, that I think the biggest advantage is being able to understand the string with just one glance.

Ambiguity and Satisfying Constraints

The layout system needs two things for Auto Layout to work properly. It needs enough constraints to define position and size for all elements, and it needs constraints not to conflict. If you don’t provide enough constraints, you end up with an undefined layout which might look different with each run. And if constraints conflict, you end up with unsatisfiable constraints and you won’t get the expected result, either.

Even though the system requires size constraints, it’s not always required that they be defined. When the size is missing, the layout system will use the intrinsic size from the UIView’s methods intrinsicContentSize. Different views may override this method in their implementation to define a preferred size.

To deal with conflicts, there is an additional property you can set on constraints that's worth mentioning: priority. Priority tells the layout system which constraint should take priority when two or more constraints are in conflict. This is very interesting because it allows for some subtle yet powerful layout behaviors such as keeping everything aligned but prioritizing the display of content.

Converting to Auto Layout

If you want to change to Auto Layout, you need to understand certain compatibility quirks. For one, you don’t need to jump to Auto Layout. At least, not right now. Auto Layout becomes enabled only when you enable it on your app. If you don’t enable it, you can go on as you are right now.

If you want to convert your whole app, however, it can be done without a problem.

Now, if you want Auto Layout code coexisting with non Auto Layout code, it can be done as well. But there are a couple of things you need to know. If you have a current hard coded layout and you add constraints to a part of that layout, Auto Layout gets enabled automatically. What happens to the rest of the views that don’t have constraints? Remember all views need to have enough constraints to unambiguously define their size and position.

Well, there is property on UIView called translatesAutoresisingMaskIntoConstraints. This is a BOOL and is on by default. It basically adds constraints that are equivalent to the current auto-resizing mask on the view. So all views will behave the way they were before. However, for the views that you are adding by programming constraints, you need to turn this off so the system doesn’t add the auto-resizing mask as constraints that conflict with the constraints you want to add. This is for constraints added in code; Interface Builder handles this for you if you set your constraints there.

So, in conclusion, Auto Layout is more powerful and more meaningful. It simplifies code and makes understanding and maintaining code much easier. A powerful layout tool like this definitely comes in handy when developing apps for devices with new screen sizes, such as the iPhone 5.