- Nibs are a nightmare when working with version control and merge tools. Now, at least, they are XML instead of a proprietary binary format, but it's still a joke…
- Auto-layout in IB is provably the worst GUI I have ever used. It's completely impossible to make it do what you actually indent. I was one of the guys cheering and wooing in the audience when it was announced at WWDC 2011, but it's proven to be a huge flop.
- I have a similar experience with storyboards.
- Having classes that may be instantiated both from code or from NIB deserialization adds a layer of complexity and messiness to your app.
- Ultimately laying out your views in code doing some simple arithmetic is easier to reason about and more likely to do what you expect. (People have no problem doing it to lay out websites with CSS–it's not that complicated.)
At the end of the day, nibs make it a little easier to get started (like using Ruby on Rails, and the Active* set of libraries), but it does not belong in a serious project, as it would add a prohibitive amount of technical debt.
AutoLayout is a constraint solver, and as such it's very easy to either over-specify or under-specify your constraints in a way where it no longer evaluates.
On top of this, AutoLayout also has a priority for each constraint such that if/when such a conflict occurs AutoLayout has some ordering as to which constraints get abandoned first.
When you run into cases where AutoLayout breaks, debugging is a chore. You have to go through your entire view hierarchy and query each view for its hasAmbiguousLayout flag, which will give you some pointers as to what views are breaking your whole layout.
Interface Builder makes this somewhat worse because it doesn't give you an easily understood 1:1 match between what you do in the UI vs. the code that gets generated out of the other end. The opacity makes it hard to triage AutoLayout failures.
We use AutoLayout in small parts of the app, and we've found that doing it in code has been preferable - for a system that is as easy to break as AutoLayout you really don't want to be poking buttons on the top of a black box in the hopes that whatever comes out the bottom is sane. If there was a more transparent mapping of Interface Builder -> NSLayoutConstraint this would be less of an issue.
Also, yes, XIB merges are one of the Prime Evils of Hell, second only to pbxproj merges.
What this means though is that a layout I can build in five minutes in Android with <GridLayout> takes hours in iOS and is utterly opaque to version control. This is a cost I have to pass on to my clients.
The API is ridiculously verbose and the visual language is underpowered and cryptic. It's sad but going back to manual frame calculations actually saved me a lot of time.
I think a lot of iOS devs don't realize how crap it is because they haven't taken the time to learn how other platforms solve these problems in a much more logical & developer friendly way.
The API, on the other hand, is very nice. Although constraints can be slightly verbose, they are ages better than having to manually re-layout views after every single change of the superview's bounds. Spring and struts are nice, but cannot replace all of the CGGeometry math which is equally as, if not more, verbose than adding constraints. Autolayout is add-and-forget. The only downside is that it is iOS6+ only.
Which are like noses. Everybody has one.
>And his opinion is that merging Nibs is a nightmare. Does he need to document how he did it, when, where, and what the room temp was at the time to "justify" an opinion?
Does he needs to elaborate more in order to justify it?
Of course.
Merging isn't even funny with regular code.
How about having a process for who works on what or when?
Either than or let a single person be responsible for the UI.
I can write UI code faster than any developer I've ever met who uses IB, and that's doubly true for class hierarchies I have subclassed for multiple apps, and triply true when it comes time to change those subclassed hierarchies. You note that IB is for simple UI layouts, but I would argue that for layouts that simple, the code is simple too.
Maybe it's a matter of how you think, but I can "see" the changes when I adjust the frames, colors, padding, resizing masks, and that's basically all IB will do for you.
IB will also happily confuse your localization effort, and introduce bugs when you ship apps with unreferenced XIBs.
I know what you mean. I'm not an iOS/Cocoa dev by any means, but when I write CSS I typically know what the outcome is going to be in my head because I've done it so many times.
#username-label { text-align:right }
#first-name-label { text-align:right }
...
#last-name-label { text-align:right }
#address-label { text-align:right }
With CSS, you get nice things like: #user-form label { text-align: right }
iOS code looks more like the first example but it goes on for hundreds of lines. You can create something like classes by creating real classes, but then you end up with inheritance hell.I find IB's WYSIWYG to be a lesser evil.
for (UILabel *l in @[self.usernameLabel, self.firstNameLabel, …]) {
l.textAlignment = UITextAlignmentRight;
l.textColor = [UIColor redColor];
} +(void)styleLabelForCertainPage:(UILabel *)label {
label.textAlignment = UITextAlignmentRight;
label.textColor = [UIColor redColor];
}
Then run those through your loops. If you're seriously considering writing a lot of lines for something trivial, then you're probably doing it wrong in Objective-C. [[UIToolbar appearance] setTintColor:[UIColor redColor]];That's probably true. But some of us learn better by doing the tedious bits (basically less magic) to see how everything works together, and then look for the path to remove the tedious bits (which would lead to using IB) once we have a better grasp of things.
So this tutorial is quite welcome.
With DCIntrospect (https://github.com/domesticcatsoftware/DCIntrospect), positioning in code actually becomes easier than nibs. You can print out the view properties, tweak positioning, then once it looks right you can get the values you need to tweak your code.
Additionally, getting to know UIAppearance and adding categories to UIColor and UIFont that return your app's standard fonts let you create a styleable application with consistent typography and color palette.
I am also anti-nibs:
Examples — NIB caching; Managing UI in two places (class & IB); Nightmare managing versioning and diffs (same from @SeoxyS), especially in a team environment; "Having classes that may be instantiated both from code or from NIB deserialization adds a layer of complexity and messiness to your app" (Repost from @SeoxyS); Want a custom UI implementation? Forget about using NIBs
Without NIB's — yes you have to write a lot more code. Concerns of code bloat are overblown. Your viewcontrollers are likely already bloated without inline UI implementations.
It really comes down to personal preference especially on smaller projects/apps, but I'd argue if you have ever worked on a large scale app that you are responsible for maintaining and enhancing long term, your opinion of NIB dependencies will change. This is especially true as your team pushes the limits of the UI and app performance. If I was going to teach you how to write an app, I'd explain what NIBs are (known pros and cons) and let you decide for yourself. Just like explaining to (my) kids about religion.
Fun fact, not all WWDC examples use NIBs. Say what?! Blasphemy!
Stanford academic guidelines endorsed and supported by Apple, Inc.
I wonder what approach Evan Doll uses at Flipboard...hmmm?
And Storyboards are certainly in principle a cool idea, but I've never seen a production app that has actually used them (please do correct me if you're reading this and use them in your own shipping app). As far as I know, Apple aren't dog-fooding them in their own apps either. I'm not sure of the benefits of introducing them as pretty much the first thing out of the gate. But I'm prepared to be wrong!
But you know what they're awesome for? Static table views.
If you want to build a grouped table view as login view, settings panel or the like, Storyboards are perfect.
I'm also a big fan of Storyboards for prototyping. You can get to a pretty good fidelity demo of your app's information architecture, and often you can re-use what you built when it's time to code the app for real.
(Though I often cut the Storyboard content out and paste it into a nib.)
Because just like NIBs, Storyboards exist as part of an app's resource bundle, which is easily viewable. It is usually fairly straightforward to examine an IPA from the store and determine whether it's using NIBs and the like.
Fly Delta app uses them all over the place (first-hand experience) - they're fantastic for static cell table views. Admittedly, merging them can be a HUGE pain, though.
> As far as I know, Apple aren't dog-fooding them in their own apps either.
From what I've heard from an Apple engineer, Apple doesn't dog-food a lot of this stuff because the tools either don't exist yet by the time they need to ship or aren't stable. A lot (most?) of their apps end up being done programatically.
We don't really use segues, though, since they seem to add complexity if you want to pass data around between the view controllers.
I'm not saying they did not work for hipmunk or for you generally but every app I have taken over that uses them extensively has been a nightmare to get back on track. Maybe I just have not been burned by the roll your own approach yet but I sure have been burned by the use xibs for everything approach.
The end product, what my nib is for, has 12 labels, three UIView border bars (1px thick), two UIViews just for a differing background color in a couple spots, and a UIImage. Now you're right, I could set all those in code, alloc all those labels and adjust their sizes and positions relative to the ones that came before and all of that jazz, and that's all fine and dandy. Until I realize that my design needs tweaking. So, instead of selecting all elements on the nib and pressing up twice for a two pixel shift, I'm sitting there editing 20 different things in a CGRect call... way more work.
So instead of doing it all in code, the way I went about was creating a subclass of UIView with a .xib file attached to it. The .xib has everything where I want it visually and it's connected to the header via properties of everything that needs to be dynamic. Then I made a custom init method that just takes in my object and returns a UIView object that is the totality of that nib loaded with the data I need it to be. All in all, instead of bloat, every time I need to return an instance of that custom subclass I effectively call something like this:
UIView *newView = [CustomClass createCustomViewWithObject:(id)object];
And that's it - I'm free to put it wherever I want up the chain in my subsequent views.1. Non-view controller views. These typically go in nibs. Custom tableview cells, tableview headers used across multiple views, custom buttons, nibs are all fine for this. (And the UITableView API accepts nibs for setting up reusable cells.)
You can certainly do custom tableview cells in Storyboards, but it's weird because I don't know how you can re-use those cells across multiple tableviews.
2. View Controllers. These I'm often using Storyboards to build. Since they're great for static tableviews, Storyboards end up having a decent chunk of stuff built in them lately. It can be nice to look at two views side by side. I seem to be grouping related view controllers together in single storyboards.
Nibs have performance penalties if they're packed down with too many objects, as every single one has to be loaded into memory. My understanding with Storyboards is that they don't have this drawback, so that's helpful.
Interface Builder is most emphatically your friend. The compile/debug cycle in iOS is sufficiently lengthy that laying out views programmatically gets very tedious very fast.
Besides realtime previewing of exactly how your view is going to look, IB also helps you understand how your layout is affected by rotations to landscape and differences in view height between device classes (3GS/4/4S vs 5).
Nibs make it easy to tweak and adjust – and even to throw away and start fresh.
Most importantly, though – every nib you use is code you do not have to maintain. If a UI object has some part of its API deprecated, your nibs don't care. They're automatically up-to-date.
Can you do every fancy thing you'd like with nibs? Certainly not. But you can do the basic braindead layouts of labels and buttons there, and you're much likelier to get what you want the first time. There's enough tedious code to wrangle in iOS as it is – don't create more for yourself by rejecting a mature, useful tool.
edit: For clarity, though, by all means, enjoy this solid tutorial so you understand how to get your hands dirty when necessary. Just don't fear the IB.