153

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

4

6 に答える 6

120

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

ファイル インスペクタの autolayout プロパティ

6.0 より前の iOS バージョンに設定されたデプロイメント ターゲットで自動レイアウトが有効なインターフェイス ファイルを使用すると、次のようなコンパイル エラーが発生します。

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

プロジェクトで autolayout を使用し、iOS4-5 との互換性を維持するオプションの 1 つは、2 つのターゲットを作成することです。1 つは配置ターゲット iOS 6.0 用で、もう 1 つは以前の iOS バージョン用です。

ここに画像の説明を入力

ストーリーボードと XIB ファイルごとに 2 つのバージョンを作成し、6.0 ターゲットで有効化された自動レイアウトを使用し、レガシー ターゲットで別のバージョンを使用することもできます。

ここに画像の説明を入力

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

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

私にとっては、複数のターゲットとインターフェイス ファイルを維持することによる複雑さのコストが、autolayout を使用する利点を上回っているように思えます。いくつかの特殊なケースを除いて、iOS4-5 の互換性が必要な場合は、単純な古い自動サイズ変更 (またはコードからの layoutSubViews) のみを使用する方がおそらくはるかに優れています。

于 2012-09-21T20:20:20.677 に答える
47

本当に2つのターゲットが必要ですか? Imre Kelé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つのターゲットを持つことも同様に機能しますが、私にはやり過ぎのようです

于 2012-09-25T23:40:32.880 に答える
4

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

于 2012-10-04T18:04:48.973 に答える
3

@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 に、autolayout ストーリーボードのデプロイ ターゲットを Project SDK(iOS 6.0) に設定しました。

willFinishLaunchingWithOptions: で、ストーリーボードのデフォルトがロードされる前にスイッチを本当にやりたかったのですが、その結果、「NSInvalidUnarchiveOperationException」が発生します。

于 2013-01-17T12:03:19.460 に答える
2

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

于 2012-12-13T03:04:37.713 に答える
0

Xibs のメイン ビュー サイズを Freeform に設定してから、Autosizing を使用するとうまくいくことがわかりました。ビューの問題のコードをいじる必要はありません。

于 2013-01-02T09:06:54.893 に答える