Совместимость с iOS 5. Часть 1.

Я начал программировать на iPhone OS (iOS) как раз в то время, когда шел переход с 3-ей версии на 4-ую. Готовых программ у меня еще тогда не было, поэтому вопросы совместимости меня не особо волновали. В этом месяце Apple выпустила iOS 5, и мы все на своих устройствах могли заметить, что очень многие программы не работали, работали плохо и работают плохо по сей день на этой версии операционной системы. В следующих нескольких постах я рассмотрю на примере своих приложений, как справляться с некоторыми проблемами совместимости и более того, как надо было писать, чтобы этих проблем не было вовсе.

В моем приложении AstroFriends у меня сделан свой UINavigationBar в цвет фона.

Однако на iOS 5 он начал показываться вот так. Не очень красиво, правда.

Все дело оказалось в том, что начиная с 5-ой версии Apple не будет вызывать drawRect, если вы не создали подкласс к элементам дизайна UINavigationBar, UIToolbar, and UITabBar. А это значит, что метод, который работал ранее, а именно создание новой категории и переопределение метода drawRect, теперь не будет работать. Вот полное разъяснение от Apple:

In iOS 5, the UINavigationBar, UIToolbar, and UITabBar implementations have changed so that the drawRect: method is not called unless it is implemented in a subclass. Apps that have re-implemented drawRect: in a category on any of these classes will find that the drawRect: method isn’t called. UIKit does link-checking to keep the method from being called in apps linked before iOS 5 but does not support this design on iOS 5 or later.

а вот метод, который прекрасно работал ранее в iOS 4. Если ты спрашивал на форумах: «Как сделать свой UINavigationBar со своим дизайном», то везде получал ответ:


@interface UINavigationBar (TransparentAdditions)
@end

@implementation UINavigationBar (TransparentAdditions)

- (void)drawRect:(CGRect)rect {
     UIImage *image = [UIImage imageNamed: @"af_nav_background.png"];
     [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}

@end

Теперь мы знаем, что исправить проблему будет очень просто, если мы просто сделаем подкласс MyNavigationBar от UINavigationBar.


#import <Foundation/Foundation.h>

@interface MyNavigationBar : UINavigationBar

@end

#import "MyNavigationBar.h"

@implementation MyNavigationBar

- (void)drawRect:(CGRect)rect {
      UIImage *image = [UIImage imageNamed: @"af_nav_background.png"];
      [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}

@end

Теперь нам осталось указать в Interface Builder-е, что в Navigation Bar мы будем использовать наш custom class.

Запускаем приложение и видим, что теперь оно правильно отображается и в старой iOS 4, и в новой iOS 5. То есть теперь, если вы хотите сделать собственный дизайн таких элементов как UINavigationBar, UIToolbar, and UITabBar, вам надо создать свой подкласс этих элементов управления и уже там определять их внешний вид. Кстати, если раньше, переопределяя метод drawRect  мы получали все Navigation Bar в приложении одного вида, то теперь мы имеем возможность менять их по своему усмотрению.

Реклама

Совместимость с iOS 5. Часть 1.: 4 комментария

  1. Спасибо. Тема актуальная — сам наелся с этим переходом ((

    теперь код пестрит

    // Pre 4.2 support
    — (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
    return [[[NetworkSingleton sharedSingleton] facebook] handleOpenURL:url];
    }

    // For 4.2+ support
    — (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
    sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
    return [[[NetworkSingleton sharedSingleton] facebook] handleOpenURL:url];
    }

    Ответить
  2. >>>То есть теперь, если вы хотите сделать собственный дизайн таких элементов как UINavigationBar, UIToolbar, and UITabBar, вам надо создать свой подкласс этих элементов управления и уже там определять их внешний вид

    совсем даже не обязательно, появился Appearence protocol: https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIAppearance_Protocol/Reference/Reference.html

    Ответить
    • В статье имелось в виду, что создание подкласса дает возможность использовать один и тот же код на 4 и 5 версии iOS. Ваш Appearence протокол не будет работать на телефонах с 4-кой, которых еще очень и очень много.

      Ответить
  3. >>>В статье имелось в виду, что создание подкласса дает возможность использовать один и тот же код на 4 и 5 версии iOS. Ваш Appearence протокол не будет работать на телефонах с 4-кой, которых еще очень и очень много.

    немного по другому применяется, если у вас есть уже код для 4 и раньше, можно просто добавить обращение к этому протоколу из тех методов, где вы задаете вид этим элементам, короче — best practice:
    // not supported on iOS4
    UITabBar *tabBar = [tabController tabBar];
    if ([tabBar respondsToSelector:@selector(setBackgroundImage:)])
    {
    // set it just for this instance
    [tabBar setBackgroundImage:[UIImage imageNamed:@»TBBackgroundImage.png»]];

    // set for all
    // [[UITabBar appearance] setBackgroundImage: …
    }
    else
    {
    // ios 4 code here
    }

    везде работает, без создания наследников, кто хочет плодить, тоже вариант )))

    Ответить

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s