DrawRect UINavigationBar не вызывается в iOS 5.0 - PullRequest
19 голосов
/ 05 октября 2011

Я переопределил (помещен в категорию, или завален) drawRect UINavigationBar, чтобы показать пользовательский фон. В iOS 5 это не работает. Что мне делать?

Ответы [ 7 ]

26 голосов
/ 07 ноября 2011

Настройка пользовательского фона для UINavigationBar для поддержки iOS5 и iOS4 тоже!

http://www.mladjanantic.com/setting-custom-background-for-uinavigationbar-what-will-work-on-ios5-and-ios4-too/

http://rogchap.com/2011/06/21/custom-navigation-bar-background-and-custom-buttons/


Как вы знаете, до выхода iOS 5 мы использовали drawRect override в 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 отвечать ToSelector, чтобы избежать сбоя на iOS4!

12 голосов
/ 23 января 2012

Вот менее уродливое решение, которое работает как для 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
11 голосов
/ 05 октября 2011

Попробуйте прочитать Примечания к выпуску iOS 5.0

В iOS 5 реализации UINavigationBar, UIToolbar и UITabBar изменились, так что метод drawRect: не вызывается, если он не реализован в подклассе. Приложения, которые повторно реализовали drawRect: в категории любого из этих классов, обнаружат, что метод drawRect: не вызывается. UIKit выполняет проверку ссылок, чтобы не вызывать метод в приложениях, связанных до iOS 5, но не поддерживает этот дизайн в iOS 5 или более поздней версии.

8 голосов
/ 05 октября 2011

Есть несколько возможных решений:

Самое быстрое решение Для самых ленивых из нас:

@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это неправильный путь.(Они просто шепчут вам в уши: «Отдайтесь темной стороне. Это единственный способ сохранить ваши приложения».)

1 голос
/ 03 ноября 2011
@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

Приведенное выше изображение позволит вам установить любое пользовательское фоновое изображение для UINavigationBar (iOS5 и iOS4).

0 голосов
/ 28 августа 2015

После iOS 5 - (void)drawRect:(CGRect)rect не вызывается, пока мы создаем категорию для UINavigationBar, но вы можете позвонить -(void)awakeFromNib и добавить весь код, который вы хотите добавить.

0 голосов
/ 24 сентября 2012

Перейдите по этой ссылке , чтобы сделать ваш код совместимым с 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
...