以前のバージョンの iOS で古いデバイスとの互換性を維持しながら、iOS 6 の新しい自動レイアウト機能を利用する最善の方法は何ですか?
6 に答える
自動レイアウトは、各 .storyboard または .xib ファイルで有効または無効にすることができます。特定のファイルを選択し、Xcode のファイル インスペクターを使用して [自動レイアウトを使用] プロパティを変更するだけです。
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) のみを使用する方がおそらくはるかに優れています。
本当に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つのターゲットを持つことも同様に機能しますが、私にはやり過ぎのようです
レイアウトの違いが大きくない場合は、Spring と Strutsを使用して要素を配置する方がはるかに簡単です。
@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」が発生します。
RRAutoLayout を使用してみてください: https://github.com/RolandasRazma/RRAutoLayout iOS5 への iOS6 AutoLayout バックポートです。
Xibs のメイン ビュー サイズを Freeform に設定してから、Autosizing を使用するとうまくいくことがわかりました。ビューの問題のコードをいじる必要はありません。