Я переопределил (поместил в категорию или swizzled) UINavigationBar drawRect, чтобы показать пользовательский фон. В iOS 5 он не работает. Что мне делать?
UINavigationBar drawRect не вызывается в iOS 5.0
Ответ 1
Есть несколько возможных решений:
Самое быстрое исправление Самый ленивый из нас:
@interface MyNavigationBar : UINavigationBar
@end
@implementation MyNavigationBar
- (void)drawRect:(CGRect)rect {
}
@end
@implementation UINavigationBar (BecauseIMLazyHacks)
/*
Another Ugly hack for iOS 5.0 support
*/
+ (Class)class {
return NSClassFromString(@"MyNavigationBar");
}
-(void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, self.frame.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(0, 0,
self.frame.size.width, self.frame.size.height), barBackground.CGImage);
}
@end
Опять же. Он работает, но вы не должны этого делать.
Другой способ, предложенный в WWDC'11, - переопределить UINavigationBar (Create MyNavigationBar) и инициализировать UINavigationController из xib, как здесь:
http://www.iosdevnotes.com/2011/09/custom-uinavigationbars-techniques/
И, наконец, используйте логический переключатель потока для iOS5.0 и iOS5.0- Используйте новый API, где это возможно.
Категории - неправильный путь, Swizzling - неправильный путь. (Они просто шепчут в ушах: "Дайте себе Темную сторону. Это единственный способ сохранить ваши приложения".)
Ответ 2
Настройка настраиваемого фона для UINavigationBar для поддержки iOS5 и iOS4 тоже!
http://rogchap.com/2011/06/21/custom-navigation-bar-background-and-custom-buttons/
Как вы знаете, до выхода iOS 5 мы использовали drawRect
переопределить в AppDelegate
для настройки UINavigationBar
.
Но знаете, iOS 5 дает нам новый метод стилизации (и старый не работает).
Как создать приложение, которое будет работать на iOS 4 и iOS 5 со стилизованным UINavigationBar
?
Вы должны сделать оба!
В AppDelegate
используйте этот код:
@implementation UINavigationBar (UINavigationBarCategory)
- (void)drawRect:(CGRect)rect {
UIImage *img = [UIImage imageNamed:@"navbar.png"];
[img drawInRect:rect];
}
@end
и в viewDidLoad
для iOS5 (в вашей реализации):
if ([self.navigationController.navigationBar respondsToSelector:@selector( setBackgroundImage:forBarMetrics:)]){
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"navbar.png"] forBarMetrics:UIBarMetricsDefault];
}
Если вы видите, здесь мы спрашиваем, будет ли navbar реагировать на выбор, чтобы избежать сбоя на iOS4!
Ответ 3
Здесь менее уродливое решение, которое работает как для iOS4, так и для 5:
@implementation UINavigationBar (CustomBackground)
- (UIImage *)barBackground
{
return [UIImage imageNamed:@"top-navigation-bar.png"];
}
- (void)didMoveToSuperview
{
//iOS5 only
if ([self respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)])
{
[self setBackgroundImage:[self barBackground] forBarMetrics:UIBarMetricsDefault];
}
}
//this doesn't work on iOS5 but is needed for iOS4 and earlier
- (void)drawRect:(CGRect)rect
{
//draw image
[[self barBackground] drawInRect:rect];
}
@end
Ответ 4
Попробуйте прочитать примечания к выпуску iOS 5.0
В iOS 5 реализации UINavigationBar, UIToolbar и UITabBar были изменены так, что метод drawRect: не вызывается, если он не реализован в подклассе. Приложения, которые повторно выполнили drawRect: в категории на любом из этих классов обнаружит, что метод drawRect: не вызывается. UIKit выполняет проверку ссылок, чтобы метод не вызывался в приложениях, связанных до iOS 5, но не поддерживает этот проект на iOS 5 или новее.
Ответ 5
@implementation UINavigationBar (MyCustomNavBar)
- (void)setBackgroudImage:(UIImage*)image
{
CGSize imageSize = [image size];
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, imageSize.height);
UIImageView *backgroundImage = [[UIImageView alloc] initWithImage:image];
backgroundImage.frame = self.bounds;
[self addSubview:backgroundImage];
[backgroundImage release];
}
@end
Вышеупомянутое swizzling позволит вам установить любое пользовательское фоновое изображение для UINavigationBar (iOS5 и iOS4).
Ответ 6
Следуйте этой , чтобы ваш код совместим с iOS4, 5 и 6.
Вам просто нужно сделать в Photoshop или другом программном обеспечении прямоугольник размером 320x44 или 640x88 (для отображения сетчатки) и импортировать его в свой проект
В AppDelegate используйте этот код (в заголовке между #import и @implementation AppDelegate):
@implementation UINavigationBar (CustomImage)
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed:@"top_bar.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
@end
В viewDidLoad используйте этот код для iOS5 и iOS6:
#if defined(__IPHONE_5_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_5_0
if ([self.navigationController.navigationBar respondsToSelector:@selector( setBackgroundImage:forBarMetrics:)]){
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"top_bar.png"] forBarMetrics:UIBarMetricsDefault];
}
#endif
Ответ 7
После того, как iOS 5 - (void)drawRect:(CGRect)rect
не вызывается, пока мы создаем категорию для UINavigationBar
, но вы можете вызвать -(void)awakeFromNib
и добавить весь код, который вы хотите добавить.