Monday, April 20, 2009

iPhone tutorial: "Tab Bar Application" part 2

In the last post I mentioned that I would probably write a short post commenting on the source of the XCode "Tab Bar Application" template. There really isn't that much to say about the source since there is very little of it - almost everything we see when running the app happens because of the objects in the xib files.

Let's take a look at one thing though. Go to XCode and select Classes/Tab1AppDelegate.m. Scroll down to the method 'didSelectViewController' and un-comment it. Edit the source so that the body of the method looks like this:

NSLog([NSString stringWithFormat:@"didSelectViewController:%@", viewController.title]);

Run the program by pressing CMD-Return and after the iPhone simulator window appears, select the XCode window and press CMD-R to bring the debugger window to the front. We do this, since this is where the text produced by NSLog() appears.

didSelectViewController is part of the UITabBarControllerDelegate protocol so we can expect the tab bar to "send this message" to us, that is, call this method when we press one of the buttons on the tab bar. Let's try that. Yes, go ahead and press the tab bar buttons in the simulator and see what happens. Did you remember to press CMD-R in XCode to bring the debugger window to the front by the way? If not, do it now.

Ok, so what happened? Not much, huh? Have we found a bug in the iPhone API or why isn't the method called? No, it's not a bug in the iPhone API but maybe in the XCode template application. Or more specifically in MainWindow.xib. To resolve the problem/bug, double-click on Resources/MainWindow.xib to start Interface Builder (IB). In IB go to the MainWindow.xib file and select "Tab Bar Controller" and press CMD-2. See that it has a 'delegate' outlet which isn't connected to anything? That's probably the explanation to the problem. Let's connect it to "Tab1 App Delegate" and see if that works better.

Remember that you have to "think backwards" (atleast in my view) to connect an outlet by CTRL-dragging in IB? Ok, start by positioning the mouse over "Tab Bar Controller". After that press and hold CTRL while you drag the mouse until it's positioned over "Tab1 App Delegate". Now release the mouse and a window should pop up. In that window, click on 'delegate'. This should have connected the 'delegate' outlet of "Tab Bar Controller". To verify this, select "Tab Bar Controller" and press CMD-2. A connection now exists to "Tab1 App Delegate", right? If not, try again! When you have succeeded, save the IB file (CMD-S).

Return to XCode and build and run (CMD-Return). Wait for iPhone Sim to start up and then select the source window in XCode again and bring up the debugger window (CMD-R).  Play around in the simulator a bit by pressing the two buttons and you should see something like this in the debugger window:

2009-04-20 22:40:14.842 Tab2[5188:20b] didSelectViewController:First 2

2009-04-20 22:40:19.972 Tab2[5188:20b] didSelectViewController:(null)

2009-04-20 22:40:22.026 Tab2[5188:20b] didSelectViewController:First 2

2009-04-20 22:40:23.227 Tab2[5188:20b] didSelectViewController:(null)

2009-04-20 22:40:24.506 Tab2[5188:20b] didSelectViewController:First 2

2009-04-20 22:40:25.746 Tab2[5188:20b] didSelectViewController:(null)

2009-04-20 22:40:27.139 Tab2[5188:20b] didSelectViewController:First 2

Wow, it works! But why do we get a "(null)" title for one of the view controllers? The second one to be specific. Go back to IB and select "First View Controller" in MainWindow.xib and press CMD-1. See that the 'title' is set to "First 2"? That's because it was set to that name in the "View Controllers" table in the "Tab Bar Controller" object in XCode (select it and press CMD-1 to verify). However, if you select the second view controller in MainWindow.xib - the one called "View Controller (Second)" and press CMD-1, you'll see that the title here is empty even though it had a name in the view controllers table in "Tab Bar Controller".

This probably has to do with the fact that the second view controller is defined in and loaded from another xib-file - Resources/SecondView.xib - but I'm not completely sure. To remedy this and set the title, select "View Controller (Second)", press CMD-1 and edit the title. Save the xib file (CMD-1) and return to XCode and build and run (CMD-R) and you'll see that it works.


  1. Thanks for the overview - this whole template was puzzling me today.

  2. Hi is it possible to use didSelectViewController to call a method in one of the views? For instance if I select item2 it will call a method in item2 class?