Włączenie automatycznego układu w iOS 6 przy zachowaniu kompatybilności wstecznej z iOS 5


153

Jaki jest najlepszy sposób, aby skorzystać z nowych funkcji automatycznego układu iOS 6, jednocześnie zapewniając kompatybilność ze starszymi urządzeniami we wcześniejszych wersjach iOS?


+1. Gdzie możesz to rozgryźć? Jakaś wskazówka?
— Janak Nirmal

@Jennis Jeszcze nie. iOS 6 zostanie oficjalnie wydany jutro (19.09.2012). Mam nadzieję, że obejmuje to dodatkową dokumentację na ten temat.
— sglantz

Jeszcze nic nie znalazłem. Dociekliwe umysły chcą wiedzieć!
— Ben Kreeger,

Nie sądzę, żeby to było możliwe. Podobnie jak scenorysy nie były możliwe na iOS4.
— Leo Natan

Poza dostarczeniem dwóch plików nib nie widzę, jak to byłoby możliwe. Ale ja się z tobą zgadzam.
— Leo Natan,

Odpowiedzi:


120

Autoukładanie można włączyć lub wyłączyć w każdym pliku .storyboard lub .xib. Po prostu zaznacz konkretny plik i zmodyfikuj właściwość „Użyj automatycznego układu” za pomocą Inspektora plików w Xcode:

autolayout w Inspektorze plików

Korzystanie z plików interfejsu z włączoną funkcją automatycznego układania z celem wdrożenia ustawionym na wersję systemu iOS starszą niż 6.0 powoduje błędy kompilacji, np .:

Błąd w MainStoryboard.storyboard: 3: Auto Layout w wersjach iOS wcześniejszych niż 6.0

Jedną z opcji użycia autoukładu w projekcie przy zachowaniu zgodności z iOS4-5 jest utworzenie dwóch celów : jednego dla celu wdrożenia iOS 6.0 i jednego dla wcześniejszej wersji iOS, np .:

wprowadź opis obrazu tutaj

Możesz również utworzyć dwie wersje dla każdego ze swoich scenorysów i plików XIB i użyć autoukładu włączonego z celem 6.0, a drugą ze starszym celem, np .:

wprowadź opis obrazu tutaj

Następnie dodajesz MainStoryBoardAutoSize do faz kompilacji elementu docelowego iOS6, a drugi plik do elementu docelowego iOS4. Możesz dowiedzieć się więcej o używaniu wielu celów tutaj .

EDYCJA: Jak odpowiedź marchinram , jeśli załadujesz pliki scenorysu z kodu i nie użyjesz ustawienia „Główna plansza” w Xcode, aby ustawić początkową scenorys, możesz użyć jednego celu.

Wydaje mi się, że koszt dodatkowej złożoności obsługi wielu celów i plików interfejsu wydaje się przeważać nad korzyściami wynikającymi z używania autoukładu. Z wyjątkiem kilku specjalnych przypadków, prawdopodobnie znacznie lepiej jest używać zwykłego starego automatycznego rozmiaru (lub layoutSubViews z kodu) wyłącznie, jeśli wymagana jest zgodność z iOS4-5.


29
Układ automatyczny wymaga systemu iOS 6 lub nowszego. Nie działa z iOS 5! Sprawdź swoje roszczenia przed wysłaniem. iOS 5 po prostu nie ma wymaganych interfejsów API (takich jak klasa NSLayoutConstraint). Jeśli mi nie wierzysz, sprawdź, czego doświadczają inni użytkownicy, gdy próbują korzystać z funkcji Autolayout w iOS 5: stackoverflow.com/questions/11252057/… stackoverflow.com/questions/11198981/…
— Imre Kelényi

1
Tak, myślę, że masz rację, myślę, że słyszałem to w niektórych filmach wwdc, ale teraz przetestowałem to na urządzeniu z iOS 5.0 i się zawiesiło. Przejdę przez te filmy i sprawdzę, gdzie je słyszałem. Mimo to masz rację, awarie na iOS 5.0
— Asad Khan,

@ ImreKelényi Jak można to przesłać do sklepu z aplikacjami? Nie jestem zbyt zaznajomiony z tym procesem, ale pomyślałem, że prześlesz jedno spakowane archiwum swojego pliku .app. Czy posiadanie dwóch celów w ogóle utrudnia ten proces? Dzięki.
— Crystal

47

Czy naprawdę potrzebujesz dwóch celów? Mam to w ten sposób, mam 2 scenorysy, jak powiedział Imre Kelényi, jeden z włączonymi układami automatycznymi, a drugi bez, a następnie w delegacie aplikacji po prostu sprawdzam, której wersji używają i wybieram odpowiednią scenorys:

#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

Posiadanie 2 celów działa równie dobrze, ale wydaje mi się to przesada


1
Masz rację. Działa to tak długo, jak ładujesz scenorysy z kodu i nie używasz ustawienia „Main Storyboard” celu w Xcode. Dodaję odniesienie do Twojej odpowiedzi z mojego postu.
— Imre Kelényi

SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TOto przesada. Po prostu przetestuj klasę tylko dla iOS 6 pod kątem zera. Zobacz developer.apple.com/library/mac/#documentation/developertools/…
— mat

tak dobre punkty, tak naprawdę nie myślałem o przywróceniu, kiedy odpowiedziałem na początku
— marchinram

Ahem, nie używaj willFinishLaunchingWithOptions - otrzymałem komunikat „Zamykanie aplikacji z powodu niezłapanego wyjątku„ NSInvalidUnarchiveOperationException ”, powód:„ Nie można utworzyć instancji klasy o nazwie NSLayoutConstraint ”” podczas uruchamiania symulatora w systemie iOS 5.1. Problem nie występuje z didFinishLaunchingWithOptions.
— Elise van Looij


3

Zainspirowany pomysłem na jeden cel @ marchinram, jest to rozwiązanie, które w końcu wymyśliłem. Dwie plansze, jedna dla rozpórek i sprężyn, a druga dla autoukładu. W podsumowaniu docelowym ustawiam scenorys autoukładu jako domyślny. Następnie w appDelegate sprawdzam, czy mimo wszystko muszę załadować storyboard 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];
    }

Ponadto ustawiłem cel wdrożenia scenorysu struts-and-springs na iOS 5.1, a scenorysu autoukładu na Project SDK (iOS 6.0).

Naprawdę chciałem dokonać przełączenia przed załadowaniem domyślnej w scenorysie, w willFinishLaunchingWithOptions: ale to skutkuje `` NSInvalidUnarchiveOperationException '', powód: `` Nie można utworzyć wystąpienia klasy o nazwie NSLayoutConstraint '' bez względu na to, co próbowałem.



0

Zauważyłem, że ustawienie głównego rozmiaru widoku Xibs na Freeform, a następnie użycie Autodopasowania działa świetnie. Żadnego zamieszania w kodzie problemu z widokiem.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.