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


153

在利用iOS 6的新自动布局功能同时仍能与iOS早期版本上的旧设备兼容的最佳方式是什么?


+1。您在哪里可以弄清楚?有什么线索吗?
Janak Nirmal

@Jennis还没有。iOS 6将于明天(9/19/2012)正式发布。希望其中包括有关该主题的一些额外文档。
sglantz 2012年

我还没找到任何东西。想问问的人都想知道!
Ben Kreeger 2012年

我认为那不可能。非常类似于iOS4上的情节提要。
Leo Natan 2012年

除了提供两个笔尖文件之外,我不知道这怎么可能。但是我同意你的看法。
Leo Natan 2012年

Answers:


120

可以在每个.storyboard或.xib文件上启用或禁用自动布局。只需选择特定文件,然后使用Xcode中的文件检查器修改“使用自动布局”属性即可:

文件检查器中的autolayout属性

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

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

在项目中使用自动布局并仍保持与iOS4-5兼容性的一种选择是创建两个目标:一个用于部署目标iOS 6.0,一个用于早期iOS版本,例如:

在此处输入图片说明

您还可以为每个故事板和XIB文件创建两个版本,并使用对6.0目标启用的自动布局,以及对旧目标启用的自动布局,例如:

在此处输入图片说明

然后,您将MainStoryBoardAutoSize添加到iOS6目标的Build阶段,并将另一个文件添加到iOS4目标。您可以在此处了解有关使用多个目标的更多信息。

编辑:正如marchinram的答案所指出的,如果您从代码加载情节提要文件,并且不使用Xcode中的“主情节提要”设置来设置初始情节提要,则可以使用单个目标。

对我来说,维护多个目标和接口文件的复杂性增加的成本似乎超过了使用自动布局的好处。除了一些特殊情况,如果需要iOS4-5兼容性,最好只使用普通的旧自动调整大小(或代码中的layoutSubViews)。


29
自动布局需要iOS 6或更高版本。它不适用于iOS 5!请在发布前验证您的声明。iOS 5根本没有必需的API(例如,类NSLayoutConstraint)。如果你不相信我,看看有什么其他的用户体验,当他们尝试使用自动布局与iOS 5:stackoverflow.com/questions/11252057/... stackoverflow.com/questions/11198981/...
伊姆雷Kelényi

1
是的,我认为您是对的,我想我在一些wwdc视频中听到了,但是现在我在iOS 5.0设备上对其进行了测试,然后崩溃了。我将浏览这些视频,并检查我在哪里听到的声音。不过,您说对了,它确实在iOS 5.0上崩溃了
Asad Khan

@ImreKelényi您如何将其提交到App Store?我对这个过程不太熟悉,但是我认为您提交了一个.app文件的压缩存档。有两个目标会使这个过程变得更加困难吗?谢谢。
水晶

47

您真的需要两个目标吗?我像这样工作,我有2个故事板,如ImreKelé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

有2个目标也可以,但对我来说似乎太过分了


1
你是对的。只要您从代码加载情节提要,并且不使用Xcode中目标的“主情节提要”设置,此方法就起作用。我在我的帖子中添加了对您答案的引用。
ImreKelényi2012年

SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO太过分了。只需针对nil测试仅适用于iOS 6的类。见developer.apple.com/library/mac/#documentation/developertools/...
亚光

是的,很好,我最初回答时并没有真正考虑过恢复
marchinram

哎呀,不要使用willFinishLaunchingWithOptions-我收到了一个“正在终止的应用程序,原因是未捕获的异常'NSInvalidUnarchiveOperationException',原因:'无法实例化名为NSLayoutConstraint的类'”,在iOS 5.1下运行模拟器。didFinishLaunchingWithOptions不会发生此问题。
Elise van Looij 2013年


3

受到@marchinram的一个目标构想的启发,这是我最终想到的解决方案。两个情节提要板,一个用于支柱和弹簧,一个用于自动布局。在目标摘要中,我将自动版式情节提要板设置为默认值。然后,在appDelegate中,检查是否毕竟需要加载6.0之前的struts-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-springs情节提要的部署目标设置为iOS 5.1,将自动布局情节提要的部署目标设置为Project SDK(iOS 6.0)。

我真的很想在将故事板中的默认值加载到willFinishLaunchingWithOptions中之前进行切换:但这会导致“ NSInvalidUnarchiveOperationException”,原因:无论我如何尝试,都无法实例化名为NSLayoutConstraint的类。



0

我发现将Xibs主视图的大小设置为Freeform,然后使用Autosizing可以解决问题。不会在代码中弄乱视图问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.