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
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]|.
Thank you so much for Auto Layout, it's a godsend. I wish we could write websites in it instead of messing around trying to align things with the crappy box model. (I hear CSS3 has something like the Visual Format?) And imperative code that manually lays out views is just the worst.
[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.
In this case I would probably do something like:
red.left = blue.right;
(Or vice-versa, depending on which edge you are positioning against).
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:
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.
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.
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.
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.
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.
We recently converted our project from IB to doing everything programmatically and could not be happier with the result.
As the app has evolved over time and grown in complexity, we felt we reached a tipping point where using IB was slowing us down more than it was helping. Same for auto-layout.
Part of this was because the app simply has a lot more functionality today than it did three years ago, which means there were a lot more nibs to manage than before. Part of it is because we started developing more custom views that did not map to any existing IB components and thus had to be done by hand anyway. Part of it is because we found we had to switch to drawing certain things programmatically for performance reasons. Either way, I'm quite glad we made the conversion.
That said, I agree that most apps should start with IB and only move onto the more complex stuff once/if the need arises. IB helps a lot out of the gate (and also makes learning the platform a lot easier since you can visually see what you're setting up). Once it gets to be a hindrance, you'll know, and you can then make the decision to switch later on. And if your app goes nowhere, then you'll have wasted less of your time.
I also strongly agree that explicit is better than implicit, and configuring a view programmatically allows you to fully specify what its behavior should be, rather than what it happens to be. When you revisit a nib several months later after originally configuring it, sometimes you forget whether the configuration option you selected in the dropdown was intentional, or was it the default, or was it merely accidentally changed at some point?
1) Storyboards are different in Xcode 5 both constraints as well as the under-the-hood XML. It's much more human readable and cleaner. Easy to merge.
2) You can separate storyboard into logical parts.
a)Signup flow
b) Sign In Flow
c) Tab1 and the rest of the navigationcontroller stack
d) Shared controllers
I second this. If you're in the business to crank out apps for the purpose of a bread and butter bottom line with more than one person working on the project, IB is the way to go. Otherwise, there's a ton of value in doing it by hand.
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
#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).
Regarding layoutSubviews, that's incorrect. Adjusting the frame will call setNeedsLayout, multiple calls of which will be coalesced to a single layoutSubviews by CoreAnimation's runloop observer.
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.
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.
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....
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.
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.
This is a really good point. I struggled with this when I was doing some CoreGraphics, I just couldn't get a line to not "blur" when it should have been crisp. The problem was exactly what you're pointing out.
FWIW, I side on the NIB/Storyboard if your UI is even remotely complicated (sort of the opposite of what the article is saying). Having to nudge a ton of controls around in code is a huge PITA and time saved using NIBs and Storyboards (properly).
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.
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.
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
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
I'm an iOS developer and I generally do what you suggest here. I create a bunch of subclasses of UIView and do my positioning via layoutSubviews, implement sizeThatFits when appropriate, etc.
Despite this I feel like Apple makes it very difficult to keep all UI code out of your view controllers. I'd go as far to say they actively encourage shoving UI code into your UIViewControllers. Take a look at the interface for UIViewController -- it is almost all view/presentation related [0]. Most of Apple's sample code and projects have view code sprinkled all over their UIViewControllers.
I feel like it is a constant fight to keep proper view/controller separation on the iOS platform.
Except UIViewController has a view property that is usually a container for a lot of other views. Sometimes it's desirable to add constraints to this view. Apple even provides API for this: UIViewController's updateViewConstraints method. I think of this as a compromise so we don't have to create a custom UIView subclass for every UIViewController subclass.
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
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!
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...
However, some pains can be removed with this tool I wrote: https://github.com/jfahrenkrug/StoryboardLint
It helps you to keep your IDs in code and in your Storyboards in sync.
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.
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?
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.
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.
>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.
the crux of the issue is the files used to store UI design data.
the OP says that apple's NIB/XIB format actually makes a change to the file every time you open it, making uncommitted changes.
with android's XML, you make changes via the designer or otherwise. As far as I'm aware, simply reading/opening the files does not create random changes to the files.
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.
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).
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.
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.
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.
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.
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].
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.
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]|.