Каков наилучший способ воспользоваться преимуществами новых функций автоматической разметки iOS 6, при этом обеспечивая совместимость со старыми устройствами на более ранних версиях iOS?
Каков наилучший способ воспользоваться преимуществами новых функций автоматической разметки iOS 6, при этом обеспечивая совместимость со старыми устройствами на более ранних версиях iOS?
Ответы:
Autolayout может быть включен или отключен для каждого файла .storyboard или .xib. Просто выберите конкретный файл и измените свойство «Use Autolayout» с помощью инспектора файлов в Xcode:
Использование файлов интерфейса с поддержкой автоматической разметки с целью развертывания, установленной на версию iOS до 6.0, приводит к ошибкам компиляции, например:
Ошибка в MainStoryboard.storyboard: 3: автоматическое расположение на версиях iOS до 6.0
Один из вариантов использования автоматической разметки в проекте и сохранения совместимости с iOS4-5 - создать две цели : одну для цели развертывания iOS 6.0 и одну для более ранней версии iOS, например:
Вы также можете создать две версии для каждого из ваших раскадровок и файлов XIB и использовать автоматическое расположение, включенное с целью 6.0, а другую - с устаревшей целью, например:
Затем вы добавляете MainStoryBoardAutoSize в фазы сборки цели iOS6, а другой файл - в цель iOS4. Вы можете узнать больше об использовании нескольких целей здесь .
РЕДАКТИРОВАТЬ: Как указывает ответ marchinram , если вы загружаете файлы раскадровки из кода и не используете настройку «Основная раскадровка» в XCode для установки исходной раскадровки, вы можете использовать одну цель.
Для меня стоимость дополнительной сложности обслуживания нескольких целевых файлов и файлов интерфейса, кажется, перевешивает преимущества использования автоматического размещения. За исключением нескольких особых случаев, вам, вероятно, гораздо лучше использовать обычный старый автоматический размер (или layoutSubViews из кода) исключительно, если требуется совместимость с iOS4-5.
Вам действительно нужны две цели? У меня получилось так, у меня есть 2 раскадровки, как сказал Имре Келеньи, одна с включенной автоматической разметкой, а другая без, затем в делегате приложения я просто проверяю, какую версию они используют, и выбираю правильную раскадровку:
#import "AppDelegate.h"
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:(v) options:NSNumericSearch] != NSOrderedAscending)
@interface AppDelegate ()
@property (strong, nonatomic) UIViewController *initialViewController;
@end
@implementation AppDelegate
@synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *mainStoryboard = nil;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) {
mainStoryboard = [UIStoryboard storyboardWithName:@"iPhone_iOS6" bundle:nil];
} else {
mainStoryboard = [UIStoryboard storyboardWithName:@"iPhone_iOS5" bundle:nil];
}
self.initialViewController = [mainStoryboard instantiateInitialViewController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.initialViewController;
[self.window makeKeyAndVisible];
return YES;
}
@end
Наличие двух целей работает так же хорошо, но мне кажется это излишним
SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO
это перебор. Просто протестируйте класс iOS 6 только для ноля. См developer.apple.com/library/mac/#documentation/developertools/...
Если различия в расположении невелики, гораздо проще использовать пружины и распорки для позиционирования элементов.
Вдохновленный одной целевой идеей @ marchinram, это решение, которое я наконец-то нашел. Две раскадровки, одна для стоек и пружин, другая для автопрокладки. В итоговой сводке я установил раскадровку автопутешествия по умолчанию. Затем в appDelegate я проверяю, нужно ли мне все-таки загрузить раскадровку pre-6.0:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
Class cls = NSClassFromString (@"NSLayoutConstraint");
if (cls == nil) {
NSString *mainStoryboardName = nil;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
mainStoryboardName = @"MainStoryboard_iPad_StrutsAndSprings";
} else {
mainStoryboardName = @"MainStoryboard_iPhone_StrutsAndSprings";
}
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:mainStoryboardName bundle:nil];
UIViewController *initialViewController = [mainStoryboard instantiateInitialViewController];
self.window.rootViewController = initialViewController;
[self.window makeKeyAndVisible];
}
Кроме того, я установил цель развертывания раскадровки "стойки и пружины" для iOS 5.1, а для раскадровки с автоматическим размещением - Project SDK (iOS 6.0).
Я действительно хотел сделать переключение до загрузки по умолчанию в раскадровке, в willFinishLaunchingWithOptions: но это приводит к «NSInvalidUnarchiveOperationException», причина: «Не удалось создать экземпляр класса с именем NSLayoutConstraint», независимо от того, что я пытался.
Попробуйте использовать RRAutoLayout: https://github.com/RolandasRazma/RRAutoLayout Это бэкпорт iOS6 AutoLayout для iOS5.