Each of the detail views will be contained in a UINavigationController. Using some IB tricks, we can put each detail view in it's own xib. As you know if you've read any of my previous posts, I'm a big fan of Interface Builder, and I think you should leverage it wherever possible. In this case we'll be using it wire almost the entire UI, with very little external code needed.
Go to GitHub and clone our repository. If you're using Xcode 4, look in the workspaces directory and open the ikhoyo-public workspace.
There are two projects in the workspace. One is called ikhoyo-top. It contains a 'kitchen sink' app showing all the techniques described on this blog. The other project is called ikhoyo-ui. It's a static library containing the UI classes that you can incorporate into your own projects or workspace.
The classes we'll be using are:
- IkhoyoDynamicTabBarController - the detail view container. DetailViewController inherits from this class.
- IkhoyoDynamicTabViewController - the base class for all the dynamic views. Each of the individual detail views inherit from this class.
Open the Connections Inspector for File's Owner. File's Owner is SampleWebView, which is a subclass of IkhoyoDynamicTabViewController. The way we determine the root view controller in the xib file is by wiring it up to the root outlet. In this case, root is wired up the the UINavigationController. This is the controller we'll be dynamically adding to the DetailViewController's tab bar.
Now look in IkhoyoDynamicTabBarController. The addTab method is called to load the dynamic tab view. In this case, it will load the SampleWebView. Let's look at the code:
IkhoyoDynamicTabViewController* ctlr = [self hasTab:name]; if (!ctlr) { Class cls = NSClassFromString(c); ctlr = [[[cls alloc] initWithNibName:c bundle:nil] autorelease]; ctlr.name = name; [ctlr view]; // Needed to force wiring in some cases ctlr.root.tabBarItem.title = name; if (image) ctlr.root.tabBarItem.image = image; NSMutableArray * vcs = [NSMutableArray arrayWithArray: [self viewControllers]]; [tabs addObject:ctlr]; [vcs addObject:ctlr.root]; [self setViewControllers:vcs animated:NO]; } [self setSelectedViewController:ctlr.root]; [ctlr start:param]; return ctlr;
The c variable contains the class name (SampleWebView). We use this to instantiate the xib. Basically, we instantiate the xib, get the root controller (which we wired up above), and add it to the tab bar's view controllers (via setViewControllers). You can also pass in the name and image that will appear in the tab bar item. Notice the [ctlr view] statement. This is related to the Interface Builder trick I described above. When we load the controller from the xib, all the wiring is not complete until the view in the xib is referenced. That's why we needed to put the view there, even though it's not used.
The addTab method is triggered from IkhoyoHomeTableViewController (in the ikhoyo-top project). To see it fire, put a breakpoint on the didSelectRowAtIndexPath method. If you start the app in the simulator and click on 'Sample Web View' in the master table view on the left, you can trace through and see how the addTab method works.
After the tab is loaded, the start method is called to do any view specific configuration. In our case, it starts the SampleWebView.
I've used Ikhoyo dynamic tab bars in several iPad apps that I've written. They're a very powerful technique to have in your toolbox for apps that have many detail views. We also learned some nice Interface Builder tricks that allow us to use IB in non-standard ways. In this case, we saw how we can make our code a bit more modular by having a UINavigationController based view residing in it's own xib file.
In the next post, I'll describe what an Ikhoyo Web View is, and why it's another powerful technique to have in our arsenal.
No comments:
Post a Comment