More permanent stuff at

23 August 2008

Adding New Views to iPhone an Application

It is becoming clear that iPhone apps are in my future. So I've been taking time lately to familiarize myself with the development environment. For me, this means getting to know Xcode and Objective-C.

One possible way to code an iPhone app involves using views. In fact, there is a wizard that lets you create a simple iPhone app that includes a view. It makes things handy.

But what happens when you want to include another view? There is no wizard to make the process easy. It took me about 30 minutes to figure out how to do this, so I thought I'd create a post out of it in the hope that it might make things a bit easier for someone in the future (myself included).

You've just created a simple Xcode iPhone project that uses a view. Xcode leaves you with a controller (which is the view) and an app delegate. For the purpose of this demonstration, I called my project "SimpleView". The files of interest are SimpleViewAppDelegate (.m and .h).

We now wish to create a second view and hook it up to the delegate.

First thing is to create the controller class.

File > New File > Cocoa Touch Classes > UIViewController subclass.

I called my class SecondView.m. Press the finish button.

Next, we create the xib. Xibs are the artifacts produced by Interface Builder and make up the GUI of most applications.

File > New File > User Interfaces > View XIB.

Unless you have very good reasons otherwise, I think it makes good sense to name the xib the same as the controller. I named by xib SecondView.xib.

After that we need to connect the xib to the controller and vice versa. Most of this is done in Interface Builder, but we need to do a few things in Xcode so that information is available to Interface Builder.

First open SimpleViewAppDelegate.h. Note the @class and then create an IBOutlet in the @interface section for your new view. This exposes it to InterfaceBuilder. Make sure to create a @property too.

Then open SimpleViewAppDelegate.m. Import SecondView.h and synthesize the new controller and tell the window to use it instead of the default view.

That is all that needs to be done in the code. Everything else will happen from Interface Builder. Open up SecondView.xib into Interface Builder. You can do this by double-clicking on SecondView.xib from Xcode.

Notice how "File's Owner" is a "NSObject". We need to set that as "SecondView."

Select the "Object Identity" tab in the property exporer. Under "Class Identity" change the class from "NSObject" to "SecondView."

Next, click on the "Connections" tab (second one, with the blue arrow). We need to link the view in SecondView.m with the actual view in the xib. Do this by dragging the little grey circle next to "view" in the Inspector to the "View" element in the main xib window.

The UI in the Inspector then changes to show the linkage.

After that, open up MainWindow.xib. We need to tell it about this shiny new view we've created. This is done by dragging a "View Controller" object from the library into the main xib window.

The controller is now there, but we need to make sure to set it to the right class.

Do this by setting the class name in the identify tab of the inspector to "SecondView," much the same as you did when you were setting the "File's Owner" earlier.

Next, in the main xib window select "SimpleView App Delegate" and select the "connections" tab in the Inspector. Notice how the Inspector indicates "secondView" has no connections. Rectify this by dragging its grey circle and dropping it on the "Second View" controller you have just added to the main xib window.

Then click on the "Attributes" tab of the Inspector. "NIB Name" should be empty. You want to set that to the name of the xib you created for the view. In our case this is "SecondView."

That's it, you've just create a new view. You can force your application to use it by modifying your controller such that it loads "secondView.view" instead of viewController.view inside of "applicationDidFinishLaunching."

Now on to the gripes...

It took me at least 30 minutes to figure this out the first time I did it. Immediately after that I decided to try it again. My thinking was along the lines of "ok, this should only take five minutes." But no, it took me about 15 minutes instead. Now it could be that I am just incredibly dense (the accusation has been leveled at me more than once), or it could be that the process is full of minute details that are easy to be forgotten.

It seems to me that this process just begs to be put into a wizard. To create another view, the exact same steps will have to be followed--you gain nothing by having just already done it once. This is the kind of thing that the Microsoft dev tools really shine at, and something all IDEs should aspire to: take the drudgery out of development.

Update: Added a title, 24 Aug.