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