Включение автоматической разметки в iOS 6 при сохранении обратной совместимости с iOS 5

153

Каков наилучший способ воспользоваться преимуществами новых функций автоматической разметки iOS 6, при этом обеспечивая совместимость со старыми устройствами на более ранних версиях iOS?

sglantz
источник
+1. Где ты в состоянии это выяснить? Любая подсказка?
Джанак Нирмал
@ Дженнис Еще нет. iOS 6 будет официально выпущена завтра (19.09.2012). Надеюсь, это включает дополнительную документацию по этому вопросу.
sglantz
Я еще ничего не нашел. Пытливые умы хотели бы знать!
Бен Крегер,
Я не думаю, что это было бы возможно. Очень похоже на раскадровки не было возможно на iOS4.
Лев Натан,
Помимо предоставления двух файлов пера, я не вижу, как это было бы возможно. Но я согласен с тобой.
Лев Натан,

Ответы:

120

Autolayout может быть включен или отключен для каждого файла .storyboard или .xib. Просто выберите конкретный файл и измените свойство «Use Autolayout» с помощью инспектора файлов в Xcode:

свойство autolayout в Инспекторе файлов

Использование файлов интерфейса с поддержкой автоматической разметки с целью развертывания, установленной на версию 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.

Имре Келеньи
источник
29
Автоматический макет требует iOS 6 или более поздней версии. Это не работает с iOS 5! Пожалуйста, подтвердите свои претензии перед публикацией. iOS 5 просто не имеет необходимых API (таких как класс NSLayoutConstraint). Если вы мне не верите, посмотрите, что испытывают другие пользователи, когда они пытаются использовать Autolayout с iOS 5: stackoverflow.com/questions/11252057/… stackoverflow.com/questions/11198981/…
Imre Kelényi
1
Да, я думаю, что вы правы. Мне кажется, я слышал это в некоторых видеороликах на wwdc, но теперь я протестировал его на устройстве iOS 5.0, и он упал. Я посмотрю эти видео и проверим, где я их услышал. Тем не менее, вы правы, что происходит сбой на iOS 5.0
Асад Хан
@ ImreKelényi Как бы вы отправили это в магазин приложений? Я не очень знаком с процессом, но я подумал, что вы отправили один zip-архив вашего .app-файла. Делает ли наличие двух целей этот процесс более сложным? Спасибо.
Кристалл
47

Вам действительно нужны две цели? У меня получилось так, у меня есть 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

Наличие двух целей работает так же хорошо, но мне кажется это излишним

marchinram
источник
1
Ты прав. Это работает до тех пор, пока вы загружаете раскадровки из кода и не используете параметр «Основной раскадровки» цели в XCode. Я добавляю ссылку на ваш ответ из моего поста.
Имре Келеньи
SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TOэто перебор. Просто протестируйте класс iOS 6 только для ноля. См developer.apple.com/library/mac/#documentation/developertools/...
матовый
да, хорошие моменты, я не особо задумывался о восстановлении, когда отвечал изначально
marchinram
О, не используйте willFinishLaunchingWithOptions - я получил «Завершающее приложение из-за необработанного исключения« NSInvalidUnarchiveOperationException », причина:« Не удалось создать экземпляр класса с именем NSLayoutConstraint »», запускающего симулятор под iOS 5.1. Проблема не возникает с didFinishLaunchingWithOptions.
Элиз ван Лоидж
4

Если различия в расположении невелики, гораздо проще использовать пружины и распорки для позиционирования элементов.

Богатая Аподака
источник
3

Вдохновленный одной целевой идеей @ 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», независимо от того, что я пытался.

Элиз ван Лоидж
источник
0

Я обнаружил, что установка размера основного вида Xibs на Freeform, а затем использование Autosizing работает на пользу. Нет проблем в коде для просмотра проблемы.

анонимное
источник