Увімкнення автоматичного макета в iOS 6, залишаючись назад сумісним з iOS 5


153

Який найкращий спосіб скористатися новими можливостями автоматичного компонування iOS 6, при цьому забезпечити сумісність зі старими пристроями на попередніх версіях iOS?


+1. Де ви могли це зрозуміти? Якась підказка?
Janak Nirmal

@Jennis Ще немає iOS 6 буде офіційно випущений завтра (19.09.2012). Будемо сподіватися, що вона включає додаткову документацію з цього питання.
sglantz

Я нічого ще не знайшов. Допитливі розуми хотіли б знати!
Бен Крігер

Я не думаю, що це було б можливо. Настільки схожі розкадровки на iOS4 не були можливі.
Лев Натан

Окрім надання двох файлів, не бачу, як це було б можливо. Але я з вами згоден.
Лев Натан

Відповіді:


120

Авторозкладку можна включити або вимкнути на кожному файлі .storyboard або .xib. Просто виберіть конкретний файл і змініть властивість "Використовувати автоматичний виклад" за допомогою інспектора файлів у Xcode:

властивість autolayout у інспекторі файлів

Використання файлів інтерфейсу з підтримкою авторозподілу з цільовою метою розгортання, встановленою на версії iOS до 6.0, призводить до помилок компіляції, наприклад:

Помилка в MainStoryboard.storyboard: 3: Автоматичний макет на версії iOS до 6.0

Один з ваших варіантів використання автоматичного розкладу в проекті та збереження сумісності з iOS4-5 - це створення двох цілей : одна для цілі розгортання iOS 6.0 та друга для більш ранньої версії iOS, наприклад:

введіть тут опис зображення

Ви також можете створити дві версії для кожного файлу розкадрів та файлів XIB, а також використовувати автовідклад, увімкнутий для цілі 6.0, а інший із попередньою ціллю, наприклад:

введіть тут опис зображення

Потім ви додаєте MainStoryBoardAutoSize до фаз збірки iOS6, а інший файл до iOS4-цілі. Ви можете дізнатися більше про використання кількох цілей тут .

EDIT: Як зазначається у відповіді marchinram , якщо ви завантажуєте файли розкадрівки з коду і не використовуєте параметр "Main Storyboard" у Xcode для встановлення початкової таблиці, ви можете використовувати одну ціль.

Для мене вартість додаткової складності підтримання декількох цілей та файлів інтерфейсу, здається, переважає переваги використання автоматичного розкладу. За винятком кількох спеціальних випадків, ви, ймовірно, набагато краще використовувати звичайний старий автоматичний розмір (або layoutSubViews з коду) виключно, якщо потрібна сумісність iOS4-5.


29
Для автоматичного розміщення потрібен iOS 6 або новішої версії. Це не працює з iOS 5! Перевірте свої претензії перед публікацією. iOS 5 просто не має необхідних API (наприклад, клас NSLayoutConstraint). Якщо ви не вірите мені, подивіться, що досвід інших користувачів , коли вони намагаються використовувати Autolayout з прошивкою 5: stackoverflow.com/questions/11252057 / ... stackoverflow.com/questions/11198981 / ...
Імре Kelényi

1
Так, я думаю, ти маєш рацію. Я думаю, що я чув це в деяких відео wwdc, але зараз я протестував його на пристрої iOS 5.0 і він вийшов з ладу. Я перегляну ці відео і перевірте, де я це почув. Тим не менш, ти маєш рацію, вона виходить з ладу на iOS 5.0
Асад Хан

@ ImreKelényi Як би ви подали це в магазин додатків? Я не надто знайомий з процесом, але я подумав, що ви подаєте один заархівований архів вашого файлу .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

Досягнення 2-х цілей також працює, але мені здається непосильним


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.
Elise van Looij


3

Натхненний однією цільовою ідеєю @ marchinram, це рішення, яке я нарешті придумав. Два рекламні дошки, один для підкосів та пружини та один для автоматичного розкладу. У цільовому підсумку я встановив розкладинку автомашини за замовчуванням. Потім у програмі appDelegate я перевіряю, чи потрібно мені завантажувати розгорнуту до 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, а розгортку автомашини - на SDK Project (iOS 6.0).

Я дуже хотів зробити перемикач перед завантаженням за замовчуванням у раскадровці, у willFinishLaunchingWithOptions: але це призводить до "NSInvalidUnarchiveOperationException", причина: "Не вдалося інстанціювати клас з іменем NSLayoutConstraint" незалежно від того, що я намагався.



0

Я знайшов, щоб встановити розмір основного виду Xibs на Freeform, а потім за допомогою функції Автоматизація працює частування. Нічого не возиться в коді для проблеми перегляду.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.