在 iOS 6 中启用自动布局,同时保持与 iOS 5 向后兼容
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12411980/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Enabling auto layout in iOS 6 while remaining backwards compatible with iOS 5
提问by sglantz
What is the best way to take advantage of the new auto layout features of iOS 6 while still providing compability with older devices on earlier versions of iOS?
什么是利用 iOS 6 的新自动布局功能的最佳方式,同时仍然提供与较早版本 iOS 上的旧设备的兼容性?
采纳答案by Imre Kelényi
Autolayout can be enabled or disabled on each .storyboard or .xib file. Just select the particular file and modify the "Use Autolayout" property using the File inspector in Xcode:
可以在每个 .storyboard 或 .xib 文件上启用或禁用自动布局。只需选择特定文件并使用 Xcode 中的文件检查器修改“使用自动布局”属性:
Using autolayout enabled interface files with the deployment target set to an iOS version prior to 6.0 results in compilation errors, e.g.:
使用启用了自动布局的接口文件并将部署目标设置为 6.0 之前的 iOS 版本会导致编译错误,例如:
Error in MainStoryboard.storyboard:3: Auto Layout on iOS Versions prior to 6.0
MainStoryboard.storyboard:3 中的错误:6.0 之前的 iOS 版本上的自动布局
One of your options to use autolayout in a project and still preserve compatibility with iOS4-5 is to create two targets: one for deployment target iOS 6.0 and one for an earlier iOS version, e.g.:
在项目中使用自动布局并仍然保持与 iOS4-5 的兼容性的一种选择是创建两个目标:一个用于部署目标 iOS 6.0,另一个用于较早的 iOS 版本,例如:
You can create two versions for each of your storyboard and XIB files as well and use the autolayout enabled with the 6.0 target and the other with the legacy target, e.g.:
您也可以为每个故事板和 XIB 文件创建两个版本,并使用 6.0 目标启用的自动布局和旧目标启用的另一个版本,例如:
You then add MainStoryBoardAutoSize to the iOS6 target's Build phases and the other file to the iOS4 target. You can learn more about using multiple targets here.
然后将 MainStoryBoardAutoSize 添加到 iOS6 目标的构建阶段,并将另一个文件添加到 iOS4 目标。您可以在此处了解有关使用多个目标的更多信息。
EDIT: As marchinram's answerpoints out, if you load you storyboard files from code and do not use the "Main Storyboard" setting in Xcode to set the initial storyboard, you can use a single target.
编辑:正如Marchinram 的回答指出的那样,如果您从代码加载故事板文件并且不使用 Xcode 中的“主故事板”设置来设置初始故事板,则可以使用单个目标。
For me, the cost of the added complexity of maintaining multiple targets and interface files seems to outweigh the benefits of using autolayout. Except for a few special cases, you are probably much better to use plain old auto sizing (or layoutSubViews from code) exclusively if iOS4-5 compatibility is required.
对我来说,维护多个目标和接口文件增加的复杂性的成本似乎超过了使用自动布局的好处。除了一些特殊情况,如果需要 iOS4-5 兼容性,您可能最好只使用普通的旧自动调整大小(或代码中的 layoutSubViews)。
回答by marchinram
Do you really need two targets? I got it working like this, I have 2 storyboard like Imre Kelényi said, one with auto layouts enabled and the other without, then in the app delegate i just check which version they are using and select the right storyboard:
你真的需要两个目标吗?我让它像这样工作,我有 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
Having 2 targets works aswell but seems like overkill to me
有 2 个目标也可以,但对我来说似乎有点矫枉过正
回答by Rich Apodaca
If the layout differences are not large, it's a lot easier to use Springs and Strutsto position elements.
如果布局差异不大,使用Springs 和 Struts定位元素会容易很多。
回答by Elise van Looij
Inspired by @marchinram's one target idea, this is the solution I finally came up with. Two storyboards, one for struts-and-springs and one for autolayout. In the target summary, I set the autolayout storyboard as the default. Then, in the appDelegate, I check whether I need to load the pre-6.0 struts-and-springs storyboard after all:
受到@marchinram 的一个目标想法的启发,这是我最终想出的解决方案。两个故事板,一个用于支柱和弹簧,一个用于自动布局。在目标摘要中,我将自动布局故事板设置为默认值。然后,在 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];
}
Also, I set the deployment target of the struts-and-springs storyboard to iOS 5.1, and that of the autolayout storyboard to Project SDK(iOS 6.0).
另外,我将struts-and-springs storyboard的部署目标设置为iOS 5.1,将autolayout storyboard的部署目标设置为Project SDK(iOS 6.0)。
I really wanted to do the switch before the default in storyboard is loaded, in willFinishLaunchingWithOptions: but that results in an 'NSInvalidUnarchiveOperationException', reason: 'Could not instantiate class named NSLayoutConstraint' no matter what I tried.
我真的很想在加载情节提要中的默认值之前进行切换,在 willFinishLaunchingWithOptions: 但这会导致“NSInvalidUnarchiveOperationException”,原因:“无论我尝试什么,都无法实例化名为 NSLayoutConstraint 的类”。
回答by Naka
Try to use RRAutoLayout: https://github.com/RolandasRazma/RRAutoLayoutIt's iOS6 AutoLayout backport to iOS5.
尝试使用 RRAutoLayout:https: //github.com/RolandasRazma/RRAutoLayout这是 iOS6 AutoLayout backport 到 iOS5。
回答by Anonymous
I've found setting the Xibs main view size to Freeform, and then using Autosizing works a treat. No messing about in code for a view issue.
我发现将 Xibs 主视图大小设置为 Freeform,然后使用 Autosizing 效果很好。不要在代码中搞乱视图问题。