Building an interface

As I mentioned in one of my earlier posts, programming these days is quite different to how it was when I first learned. You used to write a program and that was pretty much it – your program would interact with the operating system of course just by using standard functions or commands in the language you were using, and occasionally you might use some other library of functions. If you were implementing a GUI you’d need to design that on some graph paper as all the buttons etc. needed to be placed by writing code.

Nowadays, using IDEs like XCode on the Mac or Visual Studio on the PC, things are a bit different. For one thing, you never write an actual program from scratch – you create a new project, and a whole bunch of code, across several files, appears as if by magic. Your task then is to fill in your code at the relevant points, either adding to or replacing the boilerplate code that was automatically created.

Secondly, there’s probably some sort of graphical tool for producing the GUI. On the Mac this is known as Interface Builder. When you create a project in XCode, one of the files that is created for you is a .xib file (known, for some historical reason, as a “nib” file). When you click on this in XCode, up pops Interface Builder. These same tools work for both Mac and iPhone projects.

Now, at first glance this seems very nicely done – Interface Builder (I’ll call it IB for short) allows you to drag UI elements from a display list and place them where you want – in the case of iPhone projects, on an iPhone sized screen display. All the standard bits of iPhone UI are available, and when you place them IB does a very nice job of helping you position things properly with guide lines etc., it really is quite easy. Any text labels etc. can easily be typed in and the font, size, colour, etc. changed. So making the UI look like it should is about as straightforward as it could be. Of course, you’ll need to connect the UI elements to your code in some way before they actually do anything, and Apple’s way of doing this is for IB to spot certain markers in your code (for variables and functions/methods) and allow you drag a blue line indicating a connection between the UI element in question and these parts of your code.

To understand this you need some lingo, as you need to use “outlets”, “actions”, “data sources” and “delegates”:

  • Outlets are variables that the UI will interact with (the text in a text field for example)
  • Actions are methods/functions that the UI will call (the action to be performed when a certain button is pressed for example)
  • Data Sources are, well, sources of data that will be used in the UI (the choices available to the user on a picker list for example)
  • Delegates are classes that are used to handle something that Cocoa would otherwise do, but which for some reason Cocoa needs to delegate to you (populating the data of a picker for example)

In your code, if you use the keyword IBOutlet in the definition of a variable, or the keyword IBAction in the definition of a method, then IB will display these variables and methods (outlets and actions) and you can graphically (by dragging) connect input fields to outlet variables and buttons/sliders etc. to action methods. It’s worth noting in passing that IBOutlet and IBAction are effectively defined as null, they don’t do anything in terms of your code, they are merely markers for IB. Note that action methods should return IBAction, and also they normally take one argument which is the id of the ‘sender’ (i.e., the UI element that sent the message to cause the action).

So, you create the outlet variables and action methods in your code to store data from the UI or to do something when the user requests some action, connect them to the right UI elements in IB, save everything and build, and all should be well. Probably in most cases you would implement very simple action methods then connect up, save and build, then run to check you have the plumbing right before getting too far down the line of writing lots of code. Alternatively of course you might have already written and debugged some quite complicated bits of code and just need to connect it up to the UI.

Data sources and delegates are slightly clunkier in that you need to add some #pragma directives to your code but the principle is similar.

Now this is all well and good. But one problem that I’ve encountered a couple of times now is that, if you have managed to make some sort of error in IB (I think of it as doing some plumbing, or wiring everything up) then generally your code will compile fine but at runtime it will crash either on start up or when you perform some action in the UI, and all the debugger will tell you is that there is an unhandled exception. This doesn’t help you a whole lot since what it means is, some code you didn’t write and don’t understand is interacting badly with some other code you didn’t write and don’t understand. How do you track down what went wrong?

I’d love to know the answer to that, but so far I don’t. I had this a couple of times whilst going through the worked examples in the Beginning iPhone Development book, and I only fixed it by backing up and starting a project over. Then, I got bored of typing in example code and came up with a simple program of my own – at first I was pretty pleased with myself as that went well and I hooked everything up in IB and it ran and did what it should. Great, those earlier problems were clearly down to me just not really understanding what was going on. Unfortunately, several days later when I tried to add some new functionality to that program, I broke things again. Eventually I got the code for the new thing working, but the interface was still broken and it crashed on start up. So I spent some time commenting out all my new code, and removed the UI element I’d added in IB. Still crashes on start up. Clean build. Same problem.

So, I can’t help thinking there’s something less than ideal about this graphical approach to programming. In the old days you’d print off  a program listing and go through it on paper, seeing in your head how everything worked, or should work. I kind of need something similar to that now, some table in the code showing the linkages between UI elements and code elements. Or some debugging tool that will tell you when you’ve done something really dumb in Interface Builder.

I asked my friend who is a more experienced Mac programmer about this and he said the best thing is just to get it right first time. This reminds me of the Dutch genius of 1970s football, Johann Cruyff, who once said “before I make a mistake, I first do not make that mistake”.

I think what this means is that practice makes perfect, so I’d better get back to it!