views:

173

answers:

2

I have the need to draw a background image or set a tint color on a navigation bar, but I also need the option to have the navigation bar appear as it normally would. I'm currently using a category to support If my app does not specify a background image, what can I do instead to ensure the drawRect method does it normally would do?

I.E. -

@implementation UINavigationBar (UINavigationBarCategory)
- (void)drawRect:(CGRect)rect {
    if(hasImage){
        UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://myimageurl.com/img.jpg"]]];
        [img drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    }else{
        ??????
    }
}
@end
A: 

Theoretically you could do this by subclassing UINavigationBar overriding only the drawRect: method, and then calling [super drawRect:rect] when you want to use the default behavior.

But I don't believe you can in practice because you don't instantiate the UINavigationBar directly.

Solving this is possible but nontrivial, since the category method "replaces" the original method rather than subclassing it from the runtime's standpoint. This is why just using, say, super, won't work.

You should check out this post on "supersequent" implementation: http://cocoawithlove.com/2008/03/supersequent-implementation.html

(That link and some other related ideas are in the answer to this question: http://stackoverflow.com/questions/1405060/using-super-in-an-objective-c-category )

quixoto
Excellent info. Thank you.
E-Madd
A: 

I actually ended up doing something entirely different and I'm wondering why nobody hasn't discovered this before. One of the approaches I've seen in the course of my Googling on the subject was simply adding an image as a subview to the UINavigationBar. The only problem was this made the buttons in the bar not clickable. The fix was to disable user interaction on the image.

myUIImageView.userInteractionEnabled = NO; [myNavController.navigationBar addSubview:myUIImageView]; [myNavController.navigationBar sendSubviewToBack:myUIImageView];

With that, everything looks/works great and I don't have to override the drawRect method with a category, swizzle methods or any of that funky stuff. Simple and clean.

E-Madd