如何在保证应用程序与早期版本的iOS设备兼容的同时,最大限度地利用iOS 6新的自动布局功能?
如何在保证应用程序与早期版本的iOS设备兼容的同时,最大限度地利用iOS 6新的自动布局功能?
可以在每个.storyboard或.xib文件中启用或禁用自动布局。只需选择特定的文件,并使用Xcode中的文件检查器修改“使用自动布局”属性:
使用启用了自动布局的界面文件,并将部署目标设置为 iOS 6.0 之前的版本会导致编译错误,例如:MainStoryboard.storyboard 中的错误:3:iOS 版本低于 6.0 的自动布局
如果您想在项目中使用自动布局并仍然保持与 iOS4-5 的兼容性,其中一个选项是创建两个targets:一个用于部署目标 iOS 6.0,另一个用于早期的 iOS 版本,例如:
您可以为每个故事板和XIB文件创建两个版本,并使用启用了6.0目标的自动布局,另一个版本则使用旧版目标,例如:
你需要将MainStoryBoardAutoSize添加到iOS6目标的构建阶段,将另一个文件添加到iOS4目标中。如果想要了解如何使用多个目标,请在这里查看更多信息。对我而言,维护多个目标和界面文件的复杂性成本似乎超过了使用自动布局的好处。除了一些特殊情况外,如果需要iOS4-5兼容性,你可能更好地仅使用普通的自动调整大小(或从代码中使用layoutSubViews)。编辑:正如marchinram的回答所指出的那样,如果你从代码中加载storyboard文件,并且不使用Xcode中的“主故事板”设置来设置初始storyboard,则可以使用单个目标。
你真的需要两个目标吗?我按照Imre Kelényi所说的方法做到了这一点,我有两个故事板,一个启用了自动布局,另一个没有,在应用程序委托中,我只是检查他们正在使用哪个版本,然后选择正确的故事板:
#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
使用两个目标同样可行,但对我而言似乎有些过度。
SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO
这个方法有点过度。只需要将一个仅支持 iOS 6 的类与 nil 进行比较即可。请参阅 https://developer.apple.com/library/mac/#documentation/developertools/conceptual/cross_development/Using/using.html#//apple_ref/doc/uid/20002000-SW6 - matt受@marchinram独一目标思想的启发,这是我最终想出的解决方案。有两个故事板,一个是用于struts-and-springs,另一个则是用于autolayout。在目标摘要中,我将autolayout故事板设置为默认值。然后,在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];
}
尝试使用RRAutoLayout:https://github.com/RolandasRazma/RRAutoLayout。这是将iOS6的AutoLayout移植到iOS5的工具。
我发现将Xib的主视图大小设置为自由形式,然后使用自动布局效果非常好。不需要在代码中纠结于视图问题。