【问题标题】:iOS 8 top layout guide auto layout problemsiOS 8 顶部布局指南自动布局问题
【发布时间】:2014-11-15 19:53:15
【问题描述】:

更新到 iOS 8 SDK 时,我的应用程序中的一个屏幕完全坏了。 问题似乎是顶部布局指南向上移动,而不是成为其余视图的“锚”。

这是在 iOS 7 上的视图:

这是它在 iOS 8 中的样子(从 Xcode 6 View Hierarchy 调试器中捕获):

如您所见,视图显示在导航栏上方。 顶部布局指南有两个约束,一个用于上部图像视图,一个用于其下方的白色视图。 底部布局指南没有限制,只有视图的高度限制。

由于某种原因,iOS 8 决定在第一次调用 [self.view layoutIfNeeded] 后将顶部布局指南推送到 {0 -255; 0 0}。 此外,对于设备而言,视图的边界有时会显得太大(即完全按照统一的故事板 (600x600) 显示,而不是 320x480/320x568。

iOS 8 中的哪些变化可能会破坏布局?

[编辑] 以下是视图约束的完整列表:

(lldb) po self.view.constraints
<__NSArrayM 0x786ac520>(
    <NSLayoutConstraint:0x7c377bd0 V:[_UILayoutGuide:0x7c372f60]-(0)-[UIView:0x7c373120]>,
    <NSLayoutConstraint:0x7c377c00 UIView:0x7c373120.width == UIView:0x7c3730b0.width>,
    <NSLayoutConstraint:0x7c377c30 UIView:0x7c3730b0.centerX == UIView:0x7c373120.centerX>,
    <NSLayoutConstraint:0x7c377c60 H:|-(0)-[UIView:0x7c3716f0]   (Names: '|':UIView:0x7c3730b0 )>,
    <NSLayoutConstraint:0x7c377c90 UIView:0x7c3716f0.width == UIView:0x7c3730b0.width>,
    <NSLayoutConstraint:0x7c372f30 V:[_UILayoutGuide:0x7c372f60]-(129)-[UIView:0x7c3716f0]>
)

【问题讨论】:

  • 你解决了吗?
  • 我知道这有很多问题要问,但是您能发布所有限制的列表吗?有时他们会以奇怪的方式解决自己的问题,如果不看到所有这些,就很难了解正在发生的事情。
  • 我在顶层视图上发布了所有约束的列表。我认为这就足够了,因为整个视图都向上移动了......如果您需要更多信息,请告诉我!
  • 视图的边界有时显得很大;在viewDidLoad 中,无论故事板大小如何(通常为 600x600),边界仍然是。视图的边界在viewWillAppearviewDidAppear 中是正确的,因此请保存这些方法的框架/边界更新代码。
  • 您是否提交了有关此问题的错误报告?

标签: ios iphone autolayout ios8


【解决方案1】:

Extend Edges &gt; Under Top Bars 默认在属性检查器的扩展边缘部分中被选中。

尝试取消选中Under Top Bars

当我遇到这种奇怪的行为时,这对我有很多帮助。

请注意,它是一个 UIViewController 属性,因此您可以根据需要在代码中进行设置。

【讨论】:

  • 清洁解决方案。这限制了导航栏下方的主视图。
【解决方案2】:

您可以使用UIBarPositionTopAttached,也可以使用视图边界和框架,我也可以建议您并链接到Apple's documentation,这需要您一段时间才能解决问题。

解决此问题的最佳和最简单的方法就是将您的视图控制器嵌入导航控制器中,仅此而已。您可以通过选择视图控制器并转到编辑器>嵌入>导航控制器来做到这一点。(如果旧导航栏上有任何内容,您可以先将其向下拖动,将视图控制器嵌入导航中控制器,然后移动新导航栏上的栏按钮,然后删除旧导航栏)

将导航栏的translucent属性设置为NO

self.navigationController.navigationBar.translucent = NO;

这将修复视图在导航栏和状态栏下方的框架。

如果必须显示和隐藏导航栏,请使用

 if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
    self.edgesForExtendedLayout = UIRectEdgeNone;   // iOS 7 specific

在您的 viewDidLoad 方法中。

希望其中任何一个都能解决您的问题。

【讨论】:

  • 但这适用于自动布局吗?根据我的经验,操纵视图边界/框架通常会破坏自动布局。
  • 不幸的是,您的任何建议都没有为我解决问题:(
  • 您的第二个建议正是我在 AutoLayout 中使用 webView 时所需要的。 self.navigationController?.navigationBar.isTranslucent = false 是 Swift 3.1 语法。
  • @JamieBirch 很高兴它对您有用,您能否为答案投票。
  • @Mrunal 我做了:/
【解决方案3】:

我正在使用 Xcode 6.3.1,并且似乎该错误又回到了该版本(据说它已在 5.1 中修复)。我无法在 SO 上找到解决方法,所以我不得不用谷歌搜索更多信息,这里是:

无需在 IB 中执行通常的 Ctrl+拖动,只需选择您要为其执行此操作的视图,然后转到 Editor -> Pin -> Top Space to Superview。

这里是来源:LINK 它对我的情况有所帮助。

【讨论】:

    【解决方案4】:

    也有这样的问题。如果仅在 iOS8 上运行,您可以将约束从“topLayoutGuide.bottom-myView.top”更改为“topLayoutGuide.top-myView.top”。但这会破坏 iOS7 的 UI。可以在代码中编写类似的解决方法来支持这两个版本,但是在情节提要中创建 UI 时,没有机会让 UI 在两个版本中都运行良好。

    【讨论】:

    • 自 iOS 8 以来有一个新的布局属性:边距!确保从约束中取消选择“边距”,以便它在 iOS 7 下工作(从属性面板,在 Storyboard 中查看约束时...)
    • 勾选“相对于边距”没有限制。就在 iPad 上,topLayoutGuide 的高度突然变为 1068。显然,这会导致视图放置在屏幕之外的位置太低。
    • 顺便说一句,我只在 iPad 上遇到这个问题。
    • 好的,我的问题解决了。我有下一个类别:@interface UIApplication (Extensions) - (CGFloat)statusBarHeight;这与内部 iOS8 API 冲突
    • @NikitaIvaniushchenko 你能详细说明你做了什么来解决你的问题吗?
    【解决方案5】:

    您应该为界面构建器保留其中一种设备分辨率,然后在 IB 中布局您的屏幕,而不是使用统一的故事板 (600x600)。

    如果您的视图控制器在情节提要中的大小为 600x600,那么在 viewDidLoad 中,它将为您的视图控制器的视图获取该帧并相应地布局子视图。

    希望这会有所帮助..

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-04
      • 2014-06-23
      • 2015-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多