For iOS development, I don't use Interface Builder. I haven't willfully used a NIB (when I say NIB, I mean Interface Builder file, not the specific format) since iOS 2.0. In the past, I've worked with a few folks that really liked using Interface Builder. This is an argument I've had over and over.
Instead of mindlessly arguing on one side or the other of this, here's my go to points when I'm trying to win someone over.
Choosing Explicit over Implicit
Choosing to be explicit is my number one reason to do things in code instead. If someone new to the team opens up a view or view controller, they can see right away where everything is and not have to wonder if this file has a NIB.
I have spent countless hours searching for the source of a bug only to discover it's some checkbox in one of the half dozen inspectors in Interface Builder. If it was in code, it's simple to glance at the view code and see the source of the problem much quicker.
Tight Coupling
It is much harder to use Interface Builder for reusable views. I constantly create little views and reuse them all over the place. That's kind of the point of working in an object-oriented environment. If you use Interface Builder and have outlets and forget to connect the outlet in the second place you use it, you crash at runtime. This is terrible. This introduces a whole new class of bugs.
Now we have this thing that crashes simply because we're using Interface Builder instead of using code. If it was the exact same thing in code, it wouldn't crash. Even worse, the compiler can check this for you.
Not to mention, if you use lots of custom views, your NIBs will just be a bunch of invisible boxes. So now you have this tight coupling that is even harder to work with if you were to just lay it out in code.
Have you ever sat staring at some code wondering why it's not working on to realize you didn't connect the outlet or action? I hate that.
Working With Others
Have you ever had a merge conflict in a NIB. It's the worst. (Granted the XIB format has helped, but it's just awful instead of impossible now.) If you're working in a large application with several developers, you will waste an enormous amount of time dealing wit this issue.
The worst part is if it gets automatically merged wrong, you might not notice until runtime. With code, you can read the diff and understand what's happening. NIBs (in either format) are not human readable. This also makes looking at the history of a file useless. If it was code, it's just Objective-C. We're good at that.
It's Part of Xcode
This used to be more of an issue, but I think it's still worth mentioning. To put it lightly, Xcode is not the most stable piece of software in the world. The text editing part works pretty well. Every time I get a crash while editing a NIB, I grumble to myself and wish it was code even more.
The less I have to use Xcode for more than anything except a text editor with completion and a compiler, the happier I am.
Location, Location, Location
Layout code is not hard. Auto-layout is a bit more code than traditional layout, but it's still not bad. Trying to work with auto-layout in Interface Builder is maddening. Setting outlets to control built-in constraints is just silliness.
It's so simple to just override layoutSubviews and do your thing. Personally, I find this much easier to work with than auto-layout for most things.
I think this is a lot of people's biggest fear is working with layouts in code. Once you get the hang of it, it's so simple. Making your app universal becomes much more tribal than making separate NIBs for iPhone and iPad. You can simply reuse your code instead of create this tight coupling.
Bottom Line
Interface Builder itself is not bad. It does encourage bad practices, prevent reusability, make working with others more difficult, and slow your workflow. Personally, I avoid using Interface Builder (including storyboards) as much as possible. All of the projects I've worked on since 2009 haven't had NIBs unless it was out of my control.
I think you should save yourself some time, learn a few things, and start moving to code. We are programmers after all.
As a developer, designing is a big challenge. My process is a lot different than "normal designers." I design much like I code: trial and error.
When I'm programming, it's constantly running the tests to see what failed, trying a fix, repeat. It's finding a bug, try a fix, repeat. You get the idea. That's how I work. It's constantly iterating on ideas to see if they work.
When I was first starting out, I'd find myself reading entire source files to try to understand everything that was happening and only running the code very rarely. It's no surprise that were lots of bugs in this code. Letting the computer do the work for you is like the whole point. Anyway, this is how I design.
Sketching
Sometimes I start by sketching on paper or on an iPad. I only do this if I have no idea what I'm trying to do. If I can't picture what I'm trying to make in my head, I sketch. There's something about sketching that really helps me visualize the end result. Scribbling down idea after idea is where most of the actual "designing" takes place for me. Again, it's an iterative process.
So once I have a rough idea of the structure and layout, I jump into code. I don't use Interface Builder at all (on iOS anyway—Mac is a different story). I haven't used Interface Builder since my very first application (unless it was removing other people's NIBs). We'll save the why for another time.
Prototype Early
On iOS, it's so easy to just get something you can use. Just through together some UINavigationControllers, etc. A lot of developer confuse "design" with "visual design." They think it's only pretty pixels. The flow is the most important part. If your app is super pretty but no one can use it, it's pretty useless.
I like to just get something I can use on my phone with all system controls. If things feel good, then I move onto designing pixel. Most of the time, my first take is terrible and I go back to sketching. Iteration.
Pixel Time
For pixels, I work the same way. Once I have the layout, it dictates what needs some extra love. If I can't picture what I'm doing, I'll open Photoshop and mess around until I see something I like. A lot of the time, I don't save my PSDs. They are just pixel sketches. Once I know what I'm doing, I start implementing in code.
I often try to implement as much as I can in code instead of using images, but sometimes it's a lot easier to just use an image asset. I have an "asset farm" PSD with all of the assets I need. I keep this one around for when I inevitably change something.
Go
So there's no secret to getting into design. Just do it. Go get a piece of paper and start scribbling down your ideas. If you want to get better as a designer, go browser Dribbble or the App Store for inspiration. All you need is inspiration and iteration.
This is my first post on the Treehouse Blog. I did an 8 minute video tutorial on how to make a Ruby gem with Bundler. Check it out.
The code from this video can be found here: github.com/soffes/adder. Here is Ruby's module_function documentation.
Video Transcription
Hi, I’m Sam Soffes. I’m going to show you how to create and distribute a Ruby Gem. So, let’s say you have some really fancy code that adds 2 numbers together. We’re going to package this up into a Ruby Gem called Adder and you shoot it on Rubygems.org, so anyone can Gem install Adder and use our code. First off, you’ll need Bundler. If you don’t already have Bundler, you can easily install it with Gem install bundler. Now, simply Run, Bundle, Gem, and the name of your Gem. So, in this case, Adder. Great, and you can see here it generated a bunch of files for our Gem so, we’ll open this up in Sublime and try it out. So, most importantly it generated a Gem spec for us. and you can see it has some placeholder values. I’ll go ahead and fill this in. It’s a good idea to add a required Ruby version, that way if you’re using features that aren’t available in 187 or 192 or whatever, Rubygems won’t let you install it on a Ruby that’s not supported. Kind of on a side note, if all you’re using 19 for is the hash syntax, it’s a good idea to go ahead and use the old 187 syntax, so more people can use your code. I really prefer the 19 syntax, but I usually end up switching, just so I can support 187. If that’s the only change, no reason not to.
Anyway, you can see it made a Gem file and all it does is import your Gem spec, so because your Gem spec has Bundler and Rake and such, it will automatically add these to your Gem file using this line. You can see I went ahead and generated the MIT license, which is a really great open source license. It basically means anyone can do whatever they want with your stuff, which is pretty great. It also generated a rake file for us, we’ll get to this in a bit, and then a really nice placeholder “Readme” So you should definitely fill in your stuff when you get a chance. So you can see here in the live folder, it generated Adder to RB and it says Your code goes here’ [inaudible 01:59] and here it imports Adder version.
So, everything in your gem should go in a module. So, in this case it’s just Adder. It usually should match the name of your Gem for some auto-loading conventions. In Adder version, it just sets a constant called version. This is kind of a convention adapted from the generated Gem spec
here that will just pull in your current version. So, that’s real handy. You probably shouldn’t really do anything else with this file except bump the version whenever you’re releasing something new.
So, here we’ll just go ahead and make a new module method called Add. It’s going to take 2 parameters and we’ll just add them together.
So, the easiest way to try out your Gem without pushing it to Rubygems or installing it locally, you should just hop in the console. Bundler adds a really nice thing called Bundle Console, which by the way, this works anywhere, not just in a gem you create. So, now we can call Adder, Add, and Caller code, so you can do 2, 3, you should get 5. Awesome, it works. So, that’s really handy for trying out. Obviously, you should add some tests and cover that in a future post.
So, we verified that our Gem works, and we’re ready to show the world how to use our awesome Gem. First, we’ll just go ahead and commit our code. Now that we’ve committed, we can run Rake minus T, which is just a standard rake command for showing all the tasks available. So, you can see that Bundler has gone ahead and added 3 tasks for us; Build, Install, and Release. So, we’re going to go ahead and build our Gem, which is going to build version 001, and now we can just run Rake, Release, and it will fill, because we haven’t set up a Git remote yet. Because it expects you to have a remote for your project. So, Rake, Release will automatically tag your commit for that version and push it to your master, and then release it to Rubygems.
So, I’m going to go ahead and set this up on Github, and re run the command. So, you can see that it tagged it and failed again, and this is because we haven’t set up our Rubygems.org credentials. So, we just do Gem, Push to set this up, and it’s going to say you don’t have a Rubygems.org account. So, you can either go to Rubygems org/signup to make an account, so I’m just going to fill in my credentials, and now we’ve got an error saying that Gem push failed, which is what we wanted. we just wanted to sign in here. So, this is all stuff you have to do just the first time. Every time after this it’s really easy, so we’ll go ahead and do Rake,
Release again and see it tagged it and now its uploading it to Rubygems.org, and it pushed it. We can open up Safari and head to Rubygems.org/gem/adder, and see our Ruby Gem, you can see this pulled from our Gem spec. This is set up from our license file. It’s my avatar there, since I’m the owner. So, anyone can Gem install Adder and install our Gem, I’ll show you quickly how to update your Gem once you’ve got it published. We’ll head back over to Sublime.
So, lets say you wanted to make this available as a instance or class method so you can include Adder and have the add method, or you can just do Adder. Add. So, there’s a really nice Ruby thing called Module Function that this is force [sounds like 05:59] This basically does the same thing for both versions. I’ll put a link to the documentation if you’re curious how this works specifically. Again, we’ll just test this out real quick in the console. Again, you should obviously write test but for now, but I’ll just do it real quick. Adder, Add or we can just do 1 and 2 and get 3 or we can include Adder and just call Add. I’ll say 4,5,6 and get 11, so you can see both versions work, which is pretty cool. So, we’ll go over here to our version file and we’ll bump the version. Check out simver.org for more on how you should structure your version strength. Semantic versioning is really important in the Ruby community.
So, now that I have this new version, I can run status and see I’ve changed 2 files. We’ll go ahead and commit them. We’ll run Rake, Build again and it’s going to build version 002. We’ll run Rake Release and see its going to tag and get version 002 and it’s going to push it to Github and then it’s gonna push it to Rubygems. There we go, so if we head over to Rubygems.org and reload the page, you can see now 002, and here’s our version history. There we go. We can also head over to Github, right here. That’s again set in our Gem spec and we can see tags right here, and here are our two tags that Bundler created for us in that Rake task. So, pretty great.
Obviously, you should fill in these more and show how to use it and other stuff, and definitely have some tests. We’ll cover all that in a future post.
So, go release some code back to the community and enjoy.