Каков наилучший способ использовать новые функции автоматического макета iOS 6, сохраняя при этом совместимость со старыми устройствами в более ранних версиях iOS?
Включение автоматического расположения в iOS 6 при сохранении обратной совместимости с iOS 5
Ответ 1
Автозапуск можно включить или отключить на каждом файле .storyboard или .xib. Просто выберите конкретный файл и измените свойство "Использовать Autolayout", используя Инспектор файлов в Xcode:
Использование файлов интерфейса с включенным автозапуском с целью развертывания, установленной для версии iOS до 6.0, приводит к ошибкам компиляции, например:
Ошибка в MainStoryboard.storyboard: 3: Автоматическая компоновка в версиях iOS до 6.0
Один из ваших вариантов использования автозапуска в проекте и сохранение совместимости с iOS4-5 заключается в создании двух targets: один для целевого развертывания iOS 6.0 и один для более ранней версии iOS, например:
Вы можете создать две версии для каждого из ваших раскадров и XIB файлов, а также использовать автозапуск, включенный с целевым объектом 6.0, а другой с унаследованной целью, например:
Затем вы добавляете MainStoryBoardAutoSize к целевым этапам сборки iOS6, а другой - к цели iOS4. Вы можете узнать больше об использовании нескольких целей здесь.
EDIT: как ответ marchinram указывает, если вы загружаете файлы раскадровки из кода и не используете настройку "Main Storyboard" в Xcode, чтобы установить начальную раскадровку, вы можете использовать одну цель.
Для меня стоимость дополнительной сложности поддержки нескольких целей и файлов интерфейса, по-видимому, перевешивает преимущества использования автозапуска. За исключением нескольких особых случаев, вы, вероятно, гораздо лучше используете простой старый размер (или layoutSubViews из кода) исключительно, если требуется совместимость с iOS4-5.
Ответ 2
Вам действительно нужны две цели? У меня это работает, у меня есть 2 раскадровки, например, Imre Kelényi, одна с автоматическими макетами, а другая без, а затем в делегате приложения я просто проверяю, какую версию они используют, и выберите нужную раскадровку:
#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
Имея 2 цели, работает так же, но мне кажется излишним.
Ответ 3
Если различия в макете невелики, гораздо проще использовать Springs and Struts для размещения элементов.
Ответ 4
Вдохновленный @marchinram одной целевой идеей, это решение, которое я, наконец, придумал. Две раскадровки, одна для распорок и пружин и одна для автоспуска. В итоговом резюме я установил раскадровку автозапуска как значение по умолчанию. Затем, в appDelegate, я проверяю, нужно ли мне все-таки загружать раскадровку pre-6.0 struts-and-springs:
- (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];
}
Кроме того, я установил цель развертывания раскадровки struts-and-springs в iOS 5.1 и версию раскадровки автозапуска в Project SDK (iOS 6.0).
Я действительно хотел сделать переключатель до того, как значение по умолчанию в раскадровке будет загружено, в willFinishLaunchingWithOptions: но это приводит к "NSInvalidUnarchiveOperationException", причина: "Не удалось создать экземпляр класса NSLayoutConstraint" независимо от того, что я пробовал.
Ответ 5
Попробуйте использовать RRAutoLayout: https://github.com/RolandasRazma/RRAutoLayout Это iOS6 AutoLayout backport для iOS5.
Ответ 6
Я установил размер основного вида Xibs для Freeform, а затем использование Autosizing работает.
Не входите в код для проблемы с просмотром.