在iOS 6中启用自动布局,同时保持向后兼容iOS 5

什么是利用iOS 6新的自动布局function的最佳方式,同时还能在早期版本的iOS上提供旧设备的兼容性?

可以在每个.storyboard或.xib文件中启用或禁用Autolayout。 只需select特定的文件并使用Xcode中的文件检查器修改“使用Autolayout”属性:

文件检查器中的自动布局属性

将部署目标设置为iOS版本6.0之前的自动布局启用接口文件会导致编译错误,例如:

MainStoryboard.storyboard中的错误:3:iOS版本之前的自动布局6.0版本

您在项目中使用自动布局的选项之一,仍然保持与iOS4-5的兼容性,即创build两个目标 :一个用于部署目标iOS 6.0,另一个用于较早的iOS版本,例如:

在这里输入图像描述

您还可以为每个Storyboard和XIB文件创build两个版本,并使用6.0目标启用的自动布局,而另一个则使用旧目标,例如:

在这里输入图像描述

然后将MainStoryBoardAutoSize添加到iOS6目标的Build阶段,将另一个文件添加到iOS4目标。 你可以在这里了解更多关于使用多个目标

编辑:正如marchinram的答案指出,如果您从代码中加载故事板文件,而不使用Xcode中的“主故事板”设置设置初始故事板,您可以使用单个目标。

对我而言,维护多个目标和接口文件所增加的复杂性的代价似乎超过了使用自动布局的好处。 除了一些特殊情况外,如果需要兼容iOS4-5,则可能要更好地使用普通的旧自动resize(或代码中的layoutSubViews)。

你真的需要两个目标吗? 我有这样的工作,我有2像伊姆雷Kelényi故事板说,一个自动布局启用,另一个没有,然后在应用程序委托我只是检查他们正在使用的版本,并select正确的故事板:

#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个目标的作品,但似乎对我来说矫枉过正

如果布局差异不大,使用Springs和Struts来定位元素会更容易。

受@ marchinram的一个目标想法的启发,这是我终于想出的解决scheme。 两个故事板,一个用于支柱和弹簧,一个用于自动布局。 在目标摘要中,我将自动布局故事板设置为默认值。 然后,在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的类',无论我尝试了什么。

尝试使用RRAutoLayout: https : //github.com/RolandasRazma/RRAutoLayout它是iOS6的AutoLayout回到iOS5。

我发现将Xibs主视图的大小设置为Freeform,然后使用Autosizing进行处理。 在代码中查看问题没有搞错。