
Laying Out iOS UIs in Code - lyinsteve
http://harlanhaskins.com/2014/03/02/laying-out-ios-uis-in-code.html
======
bridger
I would still recommend using Auto Layout, even if you are laying out your
views without Interface Builder. (Full disclosure, I helped write Auto
Layout.)

One advantage is that it makes sure things are pixel-integral, no matter the
scale factor of the screen. For example, his code example,

button.x = self.view.width * 0.2; // Position the inset at 20% of the width.

has a pretty good chance at starting the button at x=21.845, or some other
point in-between pixels and producing a blurry line. If you do this same
relation in Auto Layout, the engine makes sure that the positions and widths
are all pixel-integral.

This is not as simple as just rounding everything, either! For example, if you
have two views

[blue][red], you want to make sure you round their shared edge either to the
left or to the right. Otherwise, there will be a gap between them. You need to
make sure you round their shared edge the same way consistently too, or it
will jump back and forth as you resize a window and produce a noticeable
jitter.

Also, in that same code example, they set a button's x position to be directly
related to the width of a view. If you ever want to support RTL interfaces,
this is a bad idea. It is relating a width to a position. In a RTL interface,
the correct code would be

button.x = self.view.width - self.view.width * 0.2 - button.width

Complicated! In general, you shouldn't convert between positions and sizes.
Instead, I would make an invisible spacer view and lay them out like this
using the layout format language

|[spacerView][button]

Then make a relation setting the spacerView's width to be 0.2 of the
superview's width. This will produce constraints that correctly work in a RTL
interface, laying it out like [button][spacerView]|.

~~~
sshumaker
No offense to the parent, but I think AutoLayout is kind of flawed. It's a
good idea in theory, but has some very rough edges in practice. When things go
wrong, it's difficult to figure out why, because all the constraint solving
happens elsewhere. You might have an over or under constrained layout and end
up with problems. In our experience, it also extracts a decent performance hit
for complicated layouts (tossing hundreds of rules into a constraint solver is
not fast).

Some things were harder than they needed to be, as well (e.g. centering a
group of vertically layed-out elements). We often needed to create spacer UI
elements to work around it.

FWIW, I rebuilt an iOS5-compatible version of AutoLayout (using Cassowary for
solving and a lot of objective-c runtime magic to maintain a shadow hierarchy
that consists of layout objects), which we even shipped for a while.
Eventually we decided to move away and write our own system, with an emphasis
on debuggability and simplicity. We ended up with a system that kept 90% of
the benefits of AutoLayout but without needing to solve constraints.

The key element was the idea of 'smart rectangles' which were used for layout.
You can set any two components explicitly of an axis (e.g. left and right) and
the others (e.g width and centerX) would be determined automatically.
Basically each rect system remembers the last two components on a given axis.

We also have the concept of a selection, which takes a group of 'rectangles'
and can perform various operations as a group, like laying them out
vertically, centering them all on an axis, and moving them as a group. This
makes it easy to do things like center a group of vertically layed out
elements (select, layout vertical, then set the selection's centerY).

The rectangles can then be applied to UI elements (which automatically handles
rounding to pixel integrals, and ensures you don't end up updating UI
unnecessarily as you build your layout, which is the problem with most of the
UIView categories). But you don't necessarily need a UIView to apply - we've
used this system for laying out OpenGL elements as well.

In practice, the code feels kinda like Autolayout:

    
    
      buttonRect.centerX = bounds.centerX;
      buttonRect.width = 100;
      buttonRect.top = widgetRect.bottom;
      buttonRect.bottom = bounds.bottom;
    

Unlike AutoLayout, you need to lay out stuff in order (e.g. you in the example
above, widgetRect.bottom has to be set already before you assign across to
buttonRect.top), but that was a small price to pay since you can step through
the debugger and instantly see any changes you're making if your layout
doesn't work out. And we don't handle constraining between non-sibling views
as nicely as AutoLayout. But for simplicity, performance, and maintainability,
it's been a huge win for us.

Hopefully we can eventually open source it - all of the devs who've used it
miss it when working on personal projects.

~~~
prawks
As someone who's written a lot of manual layout code for iOS, count me as
interested if part of your decision to open source it or not is community
interest.

------
RyanZAG
There's generally two kinds of iOS apps/devs and once you work out what
bracket you fall into, choosing between IB and code is easy.

If you're making fairly standard apps that substitute largely for websites -
eg, login screens, some data in lists, couple forms - then you will probably
want to go with IB storyboards. For these types of apps, development speed is
most essential and future changes are mostly just tweaking the UI a bit as a
large part of the functionality of the app is just pulling data from web
services or doing standard calculations and displaying the result. Storyboards
will let you get a nice looking and fairly simple UI done very fast and allow
for rapid UI changes.

However, if you are going to have 3+ devs working on your app because it's
actually the basis for a business or is very complicated, storyboards cause a
lot of merge problems. They're far harder to create automated test code for.
Refactoring your app becomes an exercise in tracking down IBOutlets. The
couple days you saved at the start with easy layout and transitions get
eclipsed by the amount of time you spend fighting IB later for changes. Also,
if you use code review tools and have a heavy peer review culture then
storyboards are a particularly bad fit.

Honestly I believe most apps fit into the first option and storyboards are the
way to go. 95%+ of the apps on the Apple Store are definitely in the first
category, and there usually isn't a need to over engineer them.

~~~
objclxt
It's important to distinguish between NIBs (or XIBs, if you prefer) and
storyboards.

NIBs can be used in even extremely complex and large applications to make
tasks easier. For example, iPhoto on iPad uses NIBs to load in UI interface
assets as it's more convenient than doing it in code - and this is an app with
a large development team and a significant codebase (there's an interesting
WWDC 2012 video available on iPhoto's iOS architecture, which is where I got
this piece of trivia from).

One of the problems with storyboards - versus NIBs - is that it can become
difficult to work at scale. Not scale in terms of team members (although that
can be a problem), but scale in terms of the size of your app's UI. A iPad app
with a a dozen different screens of content can become very hard to navigate.

Where storyboards _are_ useful is allowing those new to the platform to get up
to speed on concepts such as custom table view cells, collection views, auto
layout and the like without having to get bogged down in the large amount of
code this would normally require. They're definitely not for everyone.

Sadly, NIBs have a bit of a bad reputation with some developers. I suspect
this is mainly for historical reasons - as of Xcode 5 the XML schema has been
significantly simplified making code review and source control much easier,
and NIBs have significant advantages for newer technologies such as auto
layout.

~~~
rqebmm
One way ive found to handle scale in storyb oards (in both terms of scale) is
RBStoryboardLink which allows you to separate an app into multiple storyboards
and use placeholders to jump into another one.

------
agildehaus
Why not just use Auto Layout in pure code?

buttonView = [[UIButton alloc] init];

buttonView.translatesAutoresizingMaskIntoConstraints = NO;

[self.view addSubview:buttonView];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:buttonView
attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0f
constant:0.0f]];

... etc

It's certainly better than the stress you'll have with UIView+Positioning or
IB.

~~~
smileyborg
Apple's options for Auto Layout in code aren't the best. Check out some of the
fantastic third party APIs available.

I'm the developer of UIView+AutoLayout, which is designed to provide the API
that Apple should have in the first place (it's inspired heavily by the IB
options): [https://github.com/smileyborg/UIView-
AutoLayout](https://github.com/smileyborg/UIView-AutoLayout)

~~~
cschneid
I've used a similar one myself. Same name but different project:
[https://github.com/jrturton/UIView-
Autolayout/blob/master/So...](https://github.com/jrturton/UIView-
Autolayout/blob/master/Source/UIView%2BAutoLayout.h)

Thank you for making this area of ios dev less painful. :)

------
accatyyc
I have some problems with this post.

#1 is saying that you're restricted to point based UI's in interface builder.
This is absolutely not true. Wether you do you UI's in interface builder or
code - use auto layout!

This way you get dynamic, resolution-independent UI's that can even work
automatically with right-to-left text (realigning other elements according to
text alignment).

The way the author is doing it is still point-based (just a bit more dynamic
since he does some calculations) while auto layout has all this built in.

Yes, it is harder to get started with auto layout, but once you learn it, it
is worth it.

#2, using things like UIView+Positioning still sets your frames. And it does
so for each property you set. This means that the frame might be set 5 times
instead of one (just for slightly cleaner code). This is not good since it
might cause 5 calls to layoutSubviews instead of one (performance issue) and
also it will ruin animations (dependent on a source and target frame).

~~~
nsmnsf
Pretty much all of my experiences with auto layout in code have taken longer
both in code length and in time than just implementing -layoutSubviews.
Explicit is better than implicit, etc.

~~~
smallsharptools
Eventually you will get a handle on AutoLayout and it will become much easier.
I learned to follow a few patterns that I taught myself which are solid for my
interfaces. If I did it all in code I would be shooting myself and any other
developer who has to touch this project later.

------
SimianLogic2
If all of your layouts are created in code, every visual tweak requires an
engineer. In general I will do almost anything to NOT have to lay out views by
hand, as nothing slows a project down more than jumping into the tweak-a-
magic-number-and-recompile cycle. It sucked when I was doing CSS, and it sucks
even more when I'm compiling code.

For the most part IB mostly doesn't make sense for games, so I have a custom
Photoshop script that exports each layer with metadata. A custom importer
reads the metadata file and loads the whole view in the proper positioning. So
I've basically swapped IB for Photoshop, but the work flow is essentially the
same....

~~~
king_magic
In my extensive experience with storyboards, XIBs & NIBs, I've found it to be
incredibly easy to unintentionally change something that has a profound effect
on how that particular view works. Frankly, with iOS storyboards or XIBs, I'd
be much more comfortable _only_ having engineers handle visual tweaks.

Recent example - went into a storyboard, changed a constraint, must have
accidentally clicked on the wrong thing at one point, and the next time I ran
my app, there was a faint detail disclosure icon in the middle of my view
controller. It was absurd - somehow, unintentially, I had redirected a push
segue onto a UIImageView. No clue how it happened, but it took me a good 10
minutes to diagnose it.

IB is just way too buggy to trust non-engineers with UI work, IMO.

------
vanwesson
> I use UIView+Positioning...

Looking at that code reveals that it doesn't try to account for fractional
positioning. If you set self.center on a view that is an even number of pixels
wide, it will result in a non-pixel-aligned origin on non-retina displays,
which results in in blurry rendering. If you're iOS-7 and iPhone only these
days, that may not matter, but there are still millions of non-retina iPads
out there, and in fact you can still buy new ones on the Apple store (both the
original iPad mini and the iPad 2 are still for sale).

I've written lots of code for iOS and have generally always preferred
programmatic layout over IB, but you have to be a little more careful than
this post is implying. Beefing up your helper routines to take into account
issues like the above is critical to making sure your UIs always look their
best.

~~~
nikatwork
Do you think rounding to the nearest int in the setters would fix this issue?

I imagine it would cause the occasional 1px drift but would probably be fine
for most use cases.

~~~
vanwesson
I share your concern about drift, but in practice I've never seen it become a
problem. On the other hand, blurry views really stick out. The easiest way to
avoid them is to have a category method on UIView called something like
"alignOrigin", in which you grab the value of "self.window.screen.scale" and
make sure to snap both the x and y of the origin to be a multiple of the
reciprocal of that scale. For example, if the scale is 1, you snap to integer
bounds. If it's 2.0, you snap to multiples of 0.5. If you call that method
every time you adjust the view's position (especially after manipulating
"center"), that'll keep everything looking sharp at all times, and is future-
proof against any new screen densities Apple might someday release.

------
fomojola
As someone who has done a decent amount of Swing/Android development, I've
often wondered: why hasn't iOS historically had decent layout manager support?
I've used RelativeLayout for Android and quite frankly I've found very few
instances where it didn't do what I wanted: the reduced number of iOS form
factors makes it easier to do pixel-perfect layouts (than the thousands of
Android devices) but even AutoLayout seems like a poor replica of what the
Swing/Android layout manager-style libraries can do. I use it both from the
Android XML and from code and it makes life REALLY easy. I've done a lot of
work with storyboard/IB recently and it isn't as bad as I used to think, but
always wondered about that.

~~~
wattson12
> than the thousands of Android devices

this probably explains why android would have it but not iOS, originally iOS
only had 1 screen size and didn't need it (though it still would have been
much better). Now that new screen sizes are being released / rumoured its much
more useful

------
supercoder
I definitely side with the author. Any time we've used IB it's always ended up
in regret. Refactoring, odd layout issues, iPad / iPhone management has always
made it a headache.

It's probably a testate to how good UIKit is to code with directly that makes
it attractive.

Though whatever side you fall on, I think it's worth appreciating you have the
_choice_. I remember when doing some brief Windows Phone development, and
seemed all you had to work with was some XML API to design your interfaces. It
was awful.

------
mp3jeep01
One of the bigger takeaways from this article should be to make a decision of
where to set layout parameters, and stick with it. I'm sure we all have
opinions on using the in-code method vs IB, and can debate 'till the end of
time. As a relatively new iOS dev picking up an existing codebase, the biggest
thing I could say is be consistent. The number of times I tried setting
something in code only to find it was being changed in IB is far too many.

~~~
k-mcgrady
Very good tip and something I find myself screwing up on projects all the
time. A good example is with scroll views. There are quite a lot of parameters
than usually need to be set (zoom scale, user interaction, multi touch,
delegate). I can't count the number of times I've been debugging why it isn't
working only to find I've mistakenly set a parameter in IB and code that are
conflicting.

------
smallsharptools
No thanks. Just learn to Storyboards already. It is it that hard and Xcode can
help anyone who maintains this app. If it all in code it takes a lot of the
and effort to understand what is controlling the layout.

~~~
sekasi
Except that Storyboards are pretty detrimental to large project maintenance,
especially universal apps. AND they have a really awful habit (or most
developers do!) to keep copy IN the storyboards.. which is an unimaginably bad
practice.

Storyboards are good for small, simple apps where you're the sole developer
(or maybe a team of 1-3). Go bigger, drop storyboards.

~~~
bodhi
> they have a really awful habit (or most developers do!) to keep copy IN the
> storyboards..

If you internationalise your app, you can extract all the copy out of a
storyboard into a strings file.

------
k-mcgrady
I think this is all pretty valid. However it's important to point out the time
savings using NIB's and Storyboards. I do most of my UIs in code but
occasionally use NIB's when I'm doing layouts that include lots of objects
that would be very time consuming to code.

Recently I decided to give Storyboards a try on a project. I was shocked at
how much time it saved (no more pushing/presenting view controllers, no more
fighting tables to display custom cells) and for views that were only
displaying information and a button to push another controller I didn't even
need to create a class as the push could be done in Interface Builder. I don't
think this approach is going to work well for all apps but when you've got
something with a predetermined flow (a form for example) it saves a hell of a
lot of time.

------
tejaswiy
I see where this is coming from, but loosing the convinience of xibs + auto
layout is too great to sacrifice for me. Just thinking of how much bigger my
view controller code will get makes me shudder.

~~~
cloudwalking
Your view code shouldn't go into your view controllers, it should go into your
views. This is a mistake that is _very_ common among iOS engineers. Anything
dealing with subviews, layouts, touches, etc should go into subclasses of
UIView; view controllers should handle touches (delegation!), interact with
the navigation controller, and act as a bridge between your views and the rest
of your application code.

~~~
shadesandcolour
But why make UIView subclasses when you don't have to? If I'm just using a
tableview, and I need to lay that out, I'm not going to subclass UITableView.
I'm just going to add one to my controller or use UITableViewController. If
you're already making subclasses of UIView, then yes, do the layout code
there, but for many applications this isn't necessary, and there's no where
else to put that code.

~~~
lyinsteve
Specifically UITableView is a bad example here, because UITableView relies
heavily on the `UITableViewDelegate` and `UITableViewDataSource`.

For that, though, you should make a separate class for the TableViewModel, to
keep that code out of your ViewControllers.

~~~
shadesandcolour
Well, maybe. UITableViewDelegate and UITableViewDataSource don't have anything
to do with the layout of that tableview. But let's say I have a bunch of
labels, or textfields, or buttons or imageViews. All of those stock classes
will do a pretty good job without subclassing, and for many applications,
there's no need to subclass them. If you're doing your layout in code, where
else does the layout code go other than the Viewcontroller that manages all
those objects.

------
pavlov
The big problem with Interface Builder is that, most of the time, its layout
view bears no resemblance to what your UI actually looks like within the app.
Deciphering the meaning of overlapping grey boxes in IB is often just as
difficult as reading code. "WYSIWYG" it ain't...

I'm working on a design tool that aims to fix this:
[http://neonto.com](http://neonto.com)

Neonto Studio is a completely visual environment with support for vector
drawing, video, smart guides, multi-device layout with full previews, and so
on... There's no coding involved -- this is an app for designers.

The tool generates readable iOS and Android code, and there's no special
runtime involved, so it's ridiculously easy to take a few screens designed in
Neonto Studio and drop them into a larger app.

It's currently in alpha testing. I'm hoping to release a full beta in the next
few months. If you're interested in trying out the alpha today, I'd love to
have your help -- just drop me an email at pauli <at> neonto dot com!

~~~
NikhilVerma
Why do I have to wait for the girl to finish blowing her bubbles before I can
sign up ?

It doesn't tell me anything about the product.

------
jfahrenkrug
Don't make the mistake of thinking "Storyboard == Auto Layout". I really like
Auto Layout and I think it is much easier to understand and read when declared
in code. I strongly dislike Storyboards, though, for the 15 reasons outlined
here: [http://stackoverflow.com/questions/9404471/when-to-use-
story...](http://stackoverflow.com/questions/9404471/when-to-use-storyboard-
and-when-to-use-xibs/19457257#19457257) However, some pains can be removed
with this tool I wrote:
[https://github.com/jfahrenkrug/StoryboardLint](https://github.com/jfahrenkrug/StoryboardLint)
It helps you to keep your IDs in code and in your Storyboards in sync.

------
chromejs10
The way I've typically worked is static pages are allowed to be done in IB,
but everything else is done in code. The reasoning is that doing things in
code makes for much easier diffs and merges and also allows you to easily edit
code in things outside of XCode (I personally prefer AppCode). Doing things in
code makes thing a lot more explicit and can be setup so that the view code
doesn't have to interfere and floor the view controller's code. The main
problem is there are lots of things you can do in code that IB can't do, but
not much (if anything) the other way around. You should always be able to
write your views using pure code.

------
Zigurd
From an Android PoV I'm very skeptical of the benefits this. Unless you can
round-trip between code and a visual tool, you are unlikely to get
professional designers to touch a UI layout in code.

It's hugely valuable to get designers to adopt the SDK's design tools. Unless
the designers on a project are obstinate about that, making that more
difficult is usually a step in the wrong direction.

He also seems to be blaming the toolchain's refactoring and the declarative UI
XML for being difficult to manage. It is really that bad?

------
jarjoura
Writing a large scale iOS app with 100s of XIB based views is equivalent to
writing a Visual Basic app in my opinion. Suddenly your app is now dependent
on -awakeFromNib and subclassing requires yet another another XIB. Just some
reasons I prefer writing layouts in code (auto or not).

There are two camps of iOS Engineers in my experience. Those that feel IB
makes your life better and those that feel the opposite. Both sides make valid
points, but I vote for sticking with code as much as possible.

------
fyolnish
Related project that I'm working on: [https://github.com/fjolnir/Visual-
Layout-Language](https://github.com/fjolnir/Visual-Layout-Language)

It's a take on Apple's visual format language that allows for defining a ui
from scratch: [https://github.com/fjolnir/Visual-Layout-
Language/blob/maste...](https://github.com/fjolnir/Visual-Layout-
Language/blob/master/Mac%20Demo/test.vll)

------
nteon
I do this too, and agree. The benefits and straightforward version control
diffs are fantastic when working on a distributed team with multiple devs
touching the UI.

------
puppetmaster3
Same issue in Android. But this does not work in real life, because Designers.

Designers don't do things in code, they use the UI panel designer. end of
story.

~~~
coherentpony
>Designers don't do things in code, they use the UI panel designer.

Because designers aren't coders. If you're after the coveted designgineer,
good luck. They don't exist. Designers design things using the best tools for
_their_ job. Coders implement the design using the best tools for _their_ job.
Thinking that designers and implementers work on the same level is toxic.

~~~
puppetmaster3
That is your opinion. Designers must know the medium.

------
stcredzero
Using Tcl/Tk, one did layout interactively at the command line. It was fast
and very intuitive, especially in the way it used layout guides with easily
understandable local "laws of physics." However, it usually resulted in very
staid looking UIs. Also, such a scheme would have to be modified to be able to
deal gracefully with things like device rotation.

------
austinl

        I use UIView+Positioning, which exposes x, y, width,    
        height, right, bottom, centerX, and centerY as both 
        setters and getters.
    

IB/code aside, this is convenient. All of those properties are read-only by
default, and that's always seemed counterintuitive to me (though I'm sure
there's some purpose I'm missing).

~~~
nsmnsf
Those are struct members, not properties.

------
nicholassmith
I built an app using Storyboard last year, I'd do it again but only if the app
was reasonably simple in scope. I think we ended up with about 20+ screens,
and at that stage there was too much going on for it to be easy to work with.

Plus on a 13" laptop on the move? Oof, hard to deal with. Only really could
work with them easily on a larger monitor.

~~~
allsystemsgo
You know, you can use more than one storyboard in your app.

~~~
nicholassmith
Yeah, but to keep logic sensible the most I could break them down to was about
3 Storyboards, which is what I did in the end.

------
ja27
When I first saw Interface Builder 25 years ago, I thought it was a neat tool
for the programming-impaired. Maybe it's finally getting useful but even with
the latest iOS autolayout, I still prefer doing my own layout calculations in
code most of the time.

------
fecak
As an aside, I think it's pretty impressive that a post by someone who
graduated high school 8 months ago is being discussed and debated on the top
of HN. He says he is looking for an internship, hopefully he will get some
interest. Kudos.

------
onmydesk
It looks to me like ios7 and auto layout is partly about running on many
screen sizes. Makes you think about future devices and how your code will
fare. Worth thinking about.

You might _need_ to use IB.

~~~
yarri
We found the switch to first the iPad & then 4.0" iPhone screens to be greatly
aided by IB. The fear (?) that's always keep us with IB is that eventually the
device screen _widths_ are going to increase -- tools are supposed to help
with such issues, why not trust that IB will lead you there?

As a side note, I learned to enjoy Android layout systems. It was all a big
mystery until I could finally test layouts interactively within the latest
Android Studio [0] GUI. Although I'm not sure if I'd rather have a similar XML
schema for iOS, I'd bet that the JetBrains folks might have already thought
about doing this for their AppCode tool[1].

[0] [http://tools.android.com/tips/layout-designtime-
attributes/](http://tools.android.com/tips/layout-designtime-attributes/) [1]
[http://www.jetbrains.com/objc/whatsnew/](http://www.jetbrains.com/objc/whatsnew/)

------
blazespin
You don't want designers working in IB. You want them thinking colours,
layout, UX, esthetics - not wrestling with XCode.

~~~
smallsharptools
Who says designers need to use Xcode and IB? They can provide the comps so the
developer knows the dimensions. It should be a collaborative process, not
something that belongs to the developer or designer.

------
indubitably
oh so you mean like css

