web-dev-qa-db-ja.com

iOS 5との後方互換性を維持しながら、iOS 6で自動レイアウトを有効にする

IOSの以前のバージョンの古いデバイスとの互換性を提供しながら、iOS 6の新しい自動レイアウト機能を利用する最良の方法は何ですか?

153
sglantz

自動レイアウトは、各.storyboardまたは.xibファイルで有効または無効にできます。特定のファイルを選択し、Xcodeのファイルインスペクターを使用して「自動レイアウトを使用」プロパティを変更するだけです。

autolayout property in the File inspector

デプロイメントターゲットを6.0より前のiOSバージョンに設定して自動レイアウト対応のインターフェイスファイルを使用すると、コンパイルエラーが発生します。例:

MainStoryboard.storyboard:3のエラー:6.0より前のiOSバージョンでの自動レイアウト

プロジェクトで自動レイアウトを使用し、iOS4-5との互換性を維持するためのオプションの1つは、2つの targets を作成することです。1つはデプロイメントターゲットiOS 6.0用、もう1つは以前のiOSバージョン用です。

enter image description here

ストーリーボードとXIBファイルのそれぞれに対して2つのバージョンを作成し、6.0ターゲットで有効になっている自動レイアウトとレガシーターゲットで有効な自動レイアウトを使用できます。例:

enter image description here

次に、MainStoryBoardAutoSizeをiOS6ターゲットのビルドフェーズに追加し、他のファイルをiOS4ターゲットに追加します。複数のターゲットの使用の詳細については、こちらをご覧ください こちら

編集: marchinram's answer 指摘するように、コードからストーリーボードファイルをロードし、Xcodeの「メインストーリーボード」設定を使用して初期ストーリーボードを設定しない場合、単一のターゲットを使用できます。

私にとっては、複数のターゲットとインターフェースファイルを維持するために追加される複雑さのコストが、自動レイアウトを使用する利点を上回るようです。いくつかの特別な場合を除いて、iOS4-5との互換性が必要な場合は、従来の単純な自動サイズ変更(またはコードのlayoutSubViews)を排他的に使用することをお勧めします。

120
Imre Kelényi

本当に2つのターゲットが必要ですか?私はこのように動作しました、私はImreKelényiが言ったような2つのストーリーボードを持っています、1つは自動レイアウトを有効にし、もう1つは無効にし、アプリデリゲートで使用しているバージョンをチェックし、適切なストーリーボードを選択します:

#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つのターゲットを持つこともうまくいきますが、私にとってはやり過ぎのようです

47
marchinram

レイアウトの違いが大きくない場合は、 Springs and Struts を使用して要素を配置する方がはるかに簡単です。

4
Rich Apodaca

@marchinramの1つのターゲットアイデアに触発され、これが最終的に思いついたソリューションです。ストラットアンドスプリング用とオートレイアウト用の2つのストーリーボード。ターゲットの概要では、自動レイアウトストーリーボードをデフォルトとして設定しました。次に、appDelegateで、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という名前のクラスをインスタンス化できませんでした」.

3
Elise van Looij

RRAutoLayoutを使用してみてください。 https://github.com/RolandasRazma/RRAutoLayout iOS5 AutoLayoutバックポートはiOS5です。

2
Naka

XibsのメインビューのサイズをFreeformに設定し、自動サイズ調整を使用するとうまくいきます。ビューの問題のためにコードに混乱はありません。

0
Anonymous