Reputation: 173
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
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
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