Xcode Autolayout限制了混乱

时间:2014-03-03 00:29:47

标签: ios iphone xcode ios7 interface-builder

我有一个基于横向的视图,里面有一个SKView(skView)。我希望skView的宽度始终为视图的100%,静态高度为288.我添加了一些约束但是当我在模拟器中启动应用程序时,它给了我相同的CGSize(568 x 288) ),无论我选择iPhone 4还是3.5。

- (void)viewDidLoad {
    CGSize size = self.skView.bounds.size; // 568 x 288
    ...
}

我在这里缺少什么?

我已经设置了一个示例项目来说明手头的问题 https://github.com/kyledecot/autolayout

enter image description here

更新#1

一位用户建议我在self.skView.bounds.size中看到viewWillAppear:的价值,这会产生一些奇怪的结果(我不确定他们是否有帮助)

enter image description here

更新#2

删除所有约束并将它们重新添加为一个评论者(在我发布的github示例项目中更新)后,建议我现在有以下内容(尽管仍然破坏):

enter image description here

IB中的线条是蓝色的,我的意思是没有歧义,但它似乎仍然不起作用。

更新#3

从用户matt收到新约束并使用viewWillAppear代替viewDidLoad后,问题似乎仍然普遍存在。似乎skView的宽度永远不会符合view

的宽度

enter image description here

正如您在屏幕截图中看到的那样,文字被截断,因为在3.5英寸iPhone上skView的宽度仍然是568(iPhone 4英寸宽度的横向)。

6 个答案:

答案 0 :(得分:6)

当您的视图配置代码启动时,听起来视图的约束尚未得到解决。也就是说,那时的帧与您使用自动布局约束创建的“真实”布局不对应(哪个应该适合skViewview

我已将代码从viewWillAppear移至viewDidLayoutSubviews,结果发现,在布局过程的这个时候,viewskView的界限已经更新,它似乎适用于3.5“和4”屏幕。

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    CGSize skViewSize = self.skView.bounds.size;
    SKScene *scene = [MyScene sceneWithSize:skViewSize];
    scene.scaleMode = SKSceneScaleModeAspectFill;

    [self.skView presentScene:scene];
}

This tutorial可能会对该主题有更多了解。

顺便说一句,我已经提交了一个拉取请求,我对您的示例存储库进行了更改,以便您可以浏览更改。

答案 1 :(得分:2)

在视图控制器中处理约束之前,会调用

viewWillAppearviewDidLoad 如果您的观看仅在创建视图时依赖于大小(例如代码中的presentScene),那么您最好在viewDidAppear或“viewDidLayoutSubviews”中进行操作。
我已经在每个方法中尝试了您的代码(在评论viewWillAppear之后)并且它按预期工作。

修改
我已将scaleMode中的wiewWillAppearSKSceneScaleModeAspectFill更改为SKSceneScaleModeFill,并且效果也很好。
我认为这比仅在呈现视图控制器之后呈现场景更好。

答案 2 :(得分:2)

我认为有一种捷径方法.. 首先,你必须勾选文件检查器中的“使用自动布局”, 然后在界面构建器中显示四个按钮,1:对齐2:针脚3:重新启动自动布局问题和4:调整大小行为.. 现在选择任何对象,你想在横向和纵向模式下显示相同的对象, 然后单击第三个按钮(Reslove autolayout)..根据您的要求选择“在视图控制器中添加缺少约束”或“在视图中添加缺少约束”。

答案 3 :(得分:1)

这里有两个问题。

首先,你原来的限制是完全错误的;如果您还希望修正垂直高度,则不需要SKView顶部和底部的垂直空间!这两件事是彼此相反的。

其次,Xcode中存在一个错误。 :(您可以在第二组约束中看到它。顶部布局指南的顶部约束出错了(您可以从-288看到)。您不小心从顶部布局指南到< SKView的em> bottom (这是Xcode的错误,它可以帮到你)。以下是解决这个问题的方法:

  • 删除顶部约束。

  • 将SKView向下移动。

  • 按住Control键并拖动以再次形成顶部布局指南的顶部约束。

  • 现在选择顶部约束并手动将其常量设置为0,以使SKView再次向上移动。

结果将是:

  • SKView的高度限制为280。

  • 视图(主视图)对SKView的前导和后续水平空间约束为0,从顶部布局指南到SKView的顶部约束为0(不是-288!)。

Bingo,现在一切都会正常工作。

答案 4 :(得分:0)

实际上我不知道正确的原因,但是调用了layoutIfNeeded方法,之后会显示当前的大小。

[self.skView layoutIfNeeded];
CGSize size = self.skView.bounds.size;

答案 5 :(得分:0)

受@Michael Kessler的回答启发我做了一些实验。

viewDidAppear中,我记录了主视图,skView和场景的大小。 对于不同的scaleModes,这里是结果。

SKSceneScaleModeAspectFill

viewSize = {480,320}, skViewSize = {480,280}, sceneSize = {568,280}

SKSceneScaleModeFill

viewSize = {480,320}, skViewSize = {480,280}, sceneSize = {568,280}

SKSceneScaleModeResizeFill

viewSize = {480,320}, skViewSize = {480,280}, sceneSize = {480,280}

很明显,您想要的模式是 SKSceneScaleModeResizeFill ,以使场景大小与视图大小完全匹配。

但是你会注意到Hello,World仍然在屏幕的右侧。 原因是当SKScene初始化时设置SKLabel的位置,当场景大小不正确时,该位置在viewDidAppear

您可以在MyScene类中按如下方式重新定位它。调整SKScene的大小时,会调用此方法。

-(void)didChangeSize:(CGSize)oldSize {
    _myLabel.position = CGPointMake(self.size.width, self.size.height/2.0);
}

注意:事情似乎适用于 SKSceneScaleModeFill ,但你所拥有的是一个宽度为568的场景,缩放到适合480而不是宽度为480的场景。