Dale Webster

@greatirl

Building and distributing iOS Layouts with EverLayout

EverLayout is an iOS library that translates JSON/XML data into layouts. In this post I want to demonstrate using EverLayout to create a basic login view for a new application.

Why would you want to write your app layouts in JSON versus Xcode’s Interface Builder or just using plain code? Well there are a couple reasons:

  • Layouts written in JSON can be easily distributed by your server and downloaded by your app. You can update your app’s layout as frequently as you wish, without the App review process.
  • For development, EverLayout will connect to a local server which can deliver your layout files as you update them. This is real-time layout designing/building — you don’t need to re-compile your app to see what it looks like or how it behaves.
  • Writing layouts in code is clunky. It takes up significant space in your controllers and views and isn’t easy to read/visualise. Layouts described in a data structure can be easier to read and are kept separate from your controller logic.

You can find more information on using EverLayout from the docs.

Getting Started

For this ‘tutorial’ I’m going to assume you know how to create a new iOS project and install frameworks with Cocoapods.

Once you’ve setup your new project, you can add EverLayout to your Podfile like so:

pod 'EverLayout'

For real-time layout building I’m going to be using a companion tool called EverLayout Bridge. This application is a basic node HTTP server which will communicate with our app, sending layout updates with sockets.

To install EverLayout Bridge, use your terminal and run:

npm install -g ever-layout-bridge

Note — If you aren’t familiar with Node or npm , you may wish to visit https://nodejs.org/en/ for more info (it’s pretty awesome.)

Configuring The App

With everything installed the first thing we want to do is configure our new app to talk to EverLayout Bridge. The bridge, when running, will monitor our Layouts directory for changes and send them to the app.

So let’s start:

  • Create a Layouts directory and add it to your application.

Note — In my opinion Xcode makes for a very poor JSON editor, so I recommend using something else. Anything else. However files that aren’t created by Xcode won’t be automatically added to the app’s target unless we create a folder reference to our Layouts directory. You need to drag your Layouts directory into your project navigator and add it as a reference.

Note — The bridge can also serve images to the app by routing GET requests to an Images folder. However we don’t need to bother with this as our example will download the images instead.

  • Run ever-layout-bridge in your project directory to start the server. It will by default look for a layouts directory ‘Layouts’ on port 3000, but these options can be configured with arguments: ever-layout-bridge --layouts="MyLayouts” --port=”1234”
  • The server is now monitoring our layouts and waiting for our connection, which we should initiate in our AppDelegate.
import UIKit
import EverLayout
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
#if DEBUG
EverLayoutBridge.connectToLayoutServer()
#endif
return true
}
  • Here I am importing the EverLayout library and initialising a connection under applicationDidLoad.

Note — It only really makes sense to connect to the bridge in DEBUG mode, this isn’t something you want in production.

Double Note — Your HTTP server likely isn’t using an SSL certificate, which means we need to allow arbitrary connections for this to work. If you are unsure on how to do this, see this StackOverflow answer.

  • Compile the app, and if all has gone to plan we should see a connected message in both the Xcode console, and the terminal window.

Loading the layout

Now that our app is talking to the server, we want to load a layout in our ViewController. I know we haven’t actually written a layout yet, but that is the whole purpose of the bridge — we can run this blank app and build its layout at runtime!

  • Create a ViewController.json file in the Layouts directory.
{
"name":"ViewController"
}
  • It’s important that this file contains a name property as this is used to route layout updates.
  • Open your controller file and load the layout like so:
import UIKit
import EverLayout
class ViewController: UIViewController {
private var layout : EverLayout?
override func viewDidLoad() {
super.viewDidLoad()
let layoutData = NSData(contentsOfFile: Bundle.main.path(forResource: "ViewController", ofType: "json", inDirectory: "Layouts")!)
self.layout = EverLayout(layoutData: layoutData as! Data)
self.layout?.buildLayout(onView: self.view, viewEnvironment: self)
}
}
  • In the buildLayout call we are choosing to build the layout on the controller’s view, but using self as a view environment. This is because the controller itself will contain properties that we will reference in our layout file.
  • Compile! If all goes well, this won’t crash

Writing a layout

If your app is running and you’ve seen the connected message, we can run a quick test to see if the layout updates are working.

  • Update your ViewController.json to look like the following and hit save.
{
"name":"ViewController",
"root":{
"properties":{
"backgroundColor":"orange"
}
}
}

This basic layout is applying an orange backgroundColor to its root , which in our case in the controller’s view. Your app should look like this:

Now, let’s create a real layout:

  • Go back to your controller and add these 4 properties
public let inputUsername : UITextField = UITextField()
public let inputPassword : UITextField = UITextField()
public let buttonRegister : UIButton = UIButton()
public let buttonLogin : UIButton = UIButton()

These properties are required for our login logic, the rest we can build with JSON.

  • Copy the JSON layout from here, and paste it into your layout file. Hit save and boom… we have an app!

EverLayout has found the text input and button views in the controller and applied a set a properties and layout constraints to them. However we didn’t have to create properties for the logo or even the input labels — they were described in the layout and EverLayout created them on the fly! We’re not likely going to need these properties for any logic, so why should we see them in our controller?

  • The only thing left for our login page is to wire up our buttons:

That’s All

So that’s how EverLayout works! As a note, it’s not good practice to download your app’s logo as you launch, but I just thought it made for a neat demonstration of how powerful this can be.

EverLayout is still a work in progress and very much an experiment, if you’re interesting in learning more about the project you can check out its GitHub, and the Docs.

Thanks for reading!

More by Dale Webster

Topics of interest

More Related Stories