Sarah Geebelen
Sarah Geebelen

Reputation: 173

How to set an image of navigationbar every where in the app

I'm building an app with storyboard. Now I want on every screen in my app the same topBar/navigationbar. I want to set an image on this navigationbar. After some searching, I found this code.

@implementation UINavigationBar (CustomImage)
- (void)drawRect:(CGRect)rect
{
    UIImage *image = [UIImage imageNamed: @"topbar.jpg"];
    [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
@end  

I've put it right above my implemantation in my appdelagate.M file. But it is not working. Also does anybody knows if this is working in IOS 5.1 as well?

Kind regards.

Upvotes: 2

Views: 548

Answers (2)

A-Live
A-Live

Reputation: 8944

I used to swizzle drawRect for this purpose, you can perform swizzling at +initialize with method_exchangeImplementations (runtime.h). Now the tricky part is to call the original drawRect, as the methods are swizzled you'll need to use the custom drawing method name to call the original one. Like if you do the drawing with, you'll have [super customDrawRect:rect]; at the end

- (void)customDrawRect:(CGRect)rect { 

   ... 
   [super customDrawRect:rect];
}

#import <objc/runtime.h> 

@implementation UINavigationBar (CustomImage)

+ (void)initialize {

    Method originalDrawRectMethod = class_getInstanceMethod([self class], @selector(drawRect:));
    Method customDrawRectMethod = class_getInstanceMethod([self class], @selector(customDrawRect:));
    method_exchangeImplementations(originalDrawRectMethod, customDrawRectMethod);
}



- (void)customDrawRect:(CGRect)rect {

    UIImage *image = [UIImage imageNamed: @"topbar.jpg"];
    [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];

    // original drawRect call
    [self customDrawRect:rect];
}


@end

Upvotes: 0

Mark Granoff
Mark Granoff

Reputation: 16938

Look at UIAppearance. It allows you to change attributes across entire UI classes. For example, I have this in an app:

UIImage *img = [UIImage imageNamed: @"NavBarBackground.png"];
[[UINavigationBar appearance] setBackgroundImage:img forBarMetrics:UIBarMetricsDefault];

UIAppearance was introduced in iOS 5. The "old" way to do this was to override -drawRect: using a category for the class in question (e.g. UINavigationBar), as you did. ("Swizzling" -- exchanging your method for an SDK-provided method -- not required, by the way.)

I found, when iOS5 came out, that the drawRect trick didn't work, so I had to use UIAppearance conditionally by enclosing the above code in an if statement like so:

if ([[UINavigationBar class] respondsToSelector:@selector(appearance)]) {
    ...
}

Why conditionally? We continued to support iOS4, so iOS4 users would experience a crash if we didn't conditionalize this UIAppearance stuff. And so, we had both this and the drawRect solution in the app!

If you don't have to support iOS4, you should definitely look into UIAppearance to achieve your goals here.

Upvotes: 4

Related Questions