什么是利用 iOS6新的自动布局特性的最佳方式,同时仍然提供与早期版本的 iOS 上的老设备的兼容性?
自动布局可以启用或禁用每个。故事板或。十一号文件。只需选择特定的文件,并使用 Xcode 中的 File 检查器修改“ Use Autolayout”属性:
使用启用自动布局的接口文件,并将部署目标设置为6.0之前的 iOS 版本,会导致编译错误,例如:
在 MainStoryboard.Storyboard 中的错误: 3:6.0之前的 iOS 版本的自动布局
在项目中使用自动布局并保持与 iOS4-5兼容的一个选项是创建两个 目标: 一个用于部署目标 iOS 6.0,另一个用于早期的 iOS 版本,例如:
你也可以为你的故事板和 XIB 文件创建两个版本,并使用启用了6.0目标的自动布局和启用了遗留目标的自动布局,例如:
然后将 MainStoryBoardAutoSize 添加到 iOS6目标的 Build 阶段,将另一个文件添加到 iOS4目标。您可以了解有关使用多个目标 给你的更多信息。
编辑: 正如 Marchinram 的回答指出的那样,如果你从代码中加载故事板文件,并且不使用 Xcode 的“主故事板”设置来设置最初的故事板,你可以使用单个目标。
对我来说,维护多个目标和接口文件所增加的复杂性的成本似乎超过了使用自动布局的好处。除了一些特殊情况,如果需要 iOS4-5兼容性,您可能最好只使用普通的自动调整大小(或代码中的 layoutSubView)。
你真的需要两个目标吗?我让它像这样工作,我有2个故事板,如 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
有两个目标也可以,但对我来说有点过了
如果布局差异不大,则使用 斯普林斯和斯特鲁茨定位元素要容易得多。
尝试使用 RRAutoLayout: < a href = “ https://github.com/RolandasRazma/RRAutoLayout”rel = “ nofollow”> https://github.com/rolandasrazma/RRAutoLayout 这是 iOS6的自动布局后端到 iOS5。
我发现将 Xibs 主视图大小设置为 Freeform,然后使用自动调整视图大小是一种享受。不要为了视图问题而乱写代码。
受@marchinram 的一个目标想法的启发,这是我最终想出的解决方案。两个故事板,一个用于支柱和弹簧,一个用于自动布局。在目标摘要中,我将自动布局故事板设置为默认值。然后,我检查是否需要加载 pre-6.0 struts-and-spring 情节串连板:
- (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-spring 情节串连板的部署目标设置为 iOS 5.1,将自动布局情节串连板的部署目标设置为 Project SDK (iOS 6.0)。
我真的很想在加载情节串连板的默认值之前切换到 will FinishLaunchingWithOptions: 但是这会导致一个“ NSInvalidUnarchive veOperationException”,原因是: “无论我怎么尝试,都无法实例化名为 NSLayoutConstraint 的类”。