2
votes

What I want to do is a navigation bar with a image on it. I have a tab controller on my main view, and inside each tab I have a UINavigationController. From inside the UIViewController that my tab/navigationController calls, I could set the titleView without much problem, doing this inside the viewDidLoad method:

self.navigationItem.titleView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mylogo.png"]] autorelease];

But, I want to replace all titles in my navigationBar for this view, and it seems ugly to repeat this everywhere. So I did this on the delegate (after linking all the Outlet stuff)

self.tabOneNavController.navigationBar.topItem.titleView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mylogo.png"]] autorelease];

Again, it worked! ok, I'm almost getting there. But the point is, I've 5 tabs and all of them have navigationControllers inside. I reduced the code repetition from every internal view to only 5 times, but it still. It requires that I do that for the NavController of each tab.

Then I tried to extend the UINavigationBar to create my own, where I could set this in the initializer, and use it in the interface builder as the object class. But it doesn't seem to work. Here is what I did:

@implementation MyNavigationBar

- (id)init {
    self = [super self];

    self.tintColor = [UIColor greenColor];
    self.topItem.title = @"testing please work";

    return self;
}

@end

in the interface file MyNavigationBar inherits from UINavigationBar. But this didn't work. Should I overwrite other method? which one? is this a good practice? I'm not even sure if I should add one navigationBar for each tab, as I said, I have tabs and I want to have a navigation bar / navigate inside them. By now, after a near death experience trying to figure out how the interface builder / outlets and classes work, the code is working, I just would like to make unglify it.

Thank you!

2

2 Answers

3
votes

The problem of repeating code which you describe has an elegant solution. Objective-C supports something called a "category", which allows you to add methods to a class. A common use for this is to customize navigation and tab bars. In Xcode 4, you would do something like this to add a category on UINavigationBar:

Hit Command+N or open the "New File" dialog. Next, choose "Objective-C category" from the Cocoa Touch menu:

Creating a category

Click Next and you will be prompted to enter the name of the class that you would like to add methods to as a category. It should look something like this:

Making a Category on the NavBar

Then, you should end up with a save file dialog. A quick note about convention here. Convention is to name a category after the original class, the plus sign, and then a description of what you're adding. Here's what yours might look like:

Category Naming Convention

Once you save your file, you will need get something like this:

Empty Category

Look at that beauty. You can now override the default drawing/init methods as well as extend the functionality of the navbar.

I'd suggest looking into the init and drawRect methods, although I don't remember which ones people use. Also, please note that while under NDA, this may change in iOS 5, so just be prepared for that possibility.

3
votes

Why not define a UIViewController subclass which sets the title view via self.navigationItem.titleView and have your other view controllers extend from that class? Then you're sharing that behavior across all of your controllers without repeating the implementation.