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?
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?
Odpowiedzi:
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:
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 .:
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 .:
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.
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
SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO
to przesada. Po prostu przetestuj klasę tylko dla iOS 6 pod kątem zera. Zobacz developer.apple.com/library/mac/#documentation/developertools/…
Jeśli różnice w układzie nie są duże, znacznie łatwiej jest używać sprężyn i rozpórek do pozycjonowania elementów.
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.
Spróbuj użyć RRAutoLayout: https://github.com/RolandasRazma/RRAutoLayout To jest powrót autoukładu iOS6 do iOS5.