什么是 Xcode 6 故事板中的“限制到边距”

Posted

技术标签:

【中文标题】什么是 Xcode 6 故事板中的“限制到边距”【英文标题】:What is "Constrain to margin" in Storyboard in Xcode 6 【发布时间】:2014-11-06 14:08:07 【问题描述】:

我正在使用自动布局和约束,发现 Xcode 6 中有一个 Constrain to margins 选项,该选项在 Xcode 5 中不存在,默认情况下是选中的。

我创建了一个测试项目,然后在 ViewController 上添加了一个UITableView,框架设置为与视图相同的大小并添加了约束

Xcode 6 即使 tableview 具有与视图相同的框架,您也可以在此处看到 Xcode 建议添加 -16 作为约束,而 Xcode 5 建议添加间距 0。

现在,当您取消选中“Constrain to margin”选项时,它的行为与 Xcode 5 相同,并建议添加 0 作为约束

另外,我发现一旦我添加了 Constrain 到边距检查的约束,我不再能够在 Xcode 5 中打开故事板文件,所以这绝对是 Xcode 6 中的新东西

希望我能够正确解释我的问题。我想了解“限制到边距”的实际作用以及何时应该和不应该使用它。如果这是非常简单明了的事情,我深表歉意。

编辑

我在discussion here 中发现了一些关于布局边距的内容,不知道是否与此有关。

【问题讨论】:

无需道歉 - 这根本不明显。 +1 不用道歉,我也想问这个问题。顺便说一句:要在 Xcode5 中打开故事板,请查看:***.com/a/25298909/529243 这是我找到的最接近解释的东西:***.com/questions/25275901/… 如何禁用此功能? 是的,这才是真正的痛苦。我一直无法弄清楚如何永久取消选中它。 【参考方案1】:

我完全不明白为什么人们抱怨“Margins 会导致 ios 8 之前的任何东西彻底崩溃。

在 xib 文件或情节提要中设置相对于边距的约束不会使您的应用在 iOS7 上崩溃,并且它不会在您的 iOS7 设备上产生不同的 UI也不是,只要您不触摸代码中的UIView.layoutMarginsUIView.preservesSuperviewLayoutMargins 属性即可。

什么是 iOS8 中的边距

布局边距表示UIView内部 周围的填充,布局系统可以在布局子视图时使用该填充 - 以确保在视图边缘和子视图之间留有间隙。在这方面,它非常类似于 CSS 中与块相关的填充属性。

默认情况下,UIView 每边的布局边距为 8 磅,这不能在 Interface Builder 中更改。但是,通过在代码中设置 UIView.layoutMargins 属性(仅适用于 iOS8),您可以调整这些值。

您可以通过 Editor > Canvas > Show Layout Rectangles 让 IB 显示边距:

边距可用于帮助布局视图和子视图。默认情况下,每个UIView 都带有边距,但它们仅在您设置与边距相关的约束时才会影响视图放置。

如何使用边距

在 Interface Builder 中使用边距的唯一方法是在配置约束时检查 Relative to margin 选项。这就是你如何引导你的约束来在布局我的视图时使用边距而不是边缘。

让我们看一下在视图及其子视图之间设置前导约束的四种不同方法。对于每个约束,我们都会查看第一个描述的关联将是子视图的前导第二个将是父视图的前导。您要密切注意的是每个约束端的 Relative to margin 选项的选中和取消选中状态,因为它定义了约束是绑定到边距还是视图边缘。

    第一项(取消选中),第二项(选中):在这种情况下,我们声明子视图的左边缘应与父视图的左边距对齐(如图所示)。

    第一项(取消选中),第二项(取消选中):都使用边缘,不是边距。在这种情况下,我们声明子视图的左边缘应与父视图的左边缘对齐。

    第一项(选中),第二项(取消选中):在这种情况下,我们声明子视图的左边距应与父视图的左边缘对齐。这种布局实际上让 subview 和 superview 重叠。

    第一项(检查),第二项(检查)。这实际上与案例 2 具有相同的效果,因为 subview 和 superview 具有相同的默认边距。我们声明子视图的左边距应该与父视图的左边距对齐。

边距有什么好处

这项新功能 (iOS8) 仅在您决定使用边距时才会影响 UI 开发。

通过使用边距,您可以通过更改单个属性的值来调整与共享父视图共享公共关系的多个子视图的位置。这明显优于使用固定值设置所有关联的约束,因为如果您需要更新所有间距,而不是一个一个地更改每个值,您可以通过使用单行更新超级视图的边距来同时修改所有相关的位置像这样的代码:

self.rootView.layoutMargins = UIEdgeInsetsMake(0, 50, 0, 0);

为了说明这种好处,在以下情况下,所有子视图的左边缘都与其父视图的左边距对齐。因此,改变superview的左边距会同时影响所有的subview。

【讨论】:

感谢您的详细解释。我将此标记为已接受的答案,因为这很好地解释了事情。 感谢@Bhumit,希望这个答案对您有所帮助。 “我完全不明白人们为什么抱怨”。好吧,也许最后一个测试版的行为改变了,我还没有检查过。但至少在几个月前,即使您没有尝试在代码中设置 layoutMargins,它也确实会导致崩溃。 值得指出的是,在添加新约束时,较新版本的 Xcode 允许您取消选中“Constrain to Margins”框,该框设置相同的“Relative to Margins”标志。这很有用,因为它可以节省几次点击!顺便说一句,答案很好,解释得很好,图片很有帮助。 我注意到图片托管在 Dropbox 上。在 SO 上托管图像不是更好吗?【参考方案2】:

在 iOS 8 中,您现在可以选择相对于超级视图边界的预定义边距来定义约束,而不是超级视图本身的边界。是的,它与您在文档中指出的布局边距完全相关。一个优点是您可以动态地重新定义边距,或者为每种设备以不同方式重新定义边距,并且布局将相应地更新而无需修改约束。

何时使用它:当您想利用这种新的灵活性时。

何时不使用它:适用于任何在 iOS 7 或更低版本上运行的应用程序。

【讨论】:

这将是一个不错的功能,如果它在默认情况下没有启用,但会导致 iOS 8 之前的任何东西彻底崩溃。【参考方案3】:

UIView 上的属性是:layoutMargins。请参阅Apple Docs。基本上,如果布局边距为 8,8,8,8(默认值),则前导空间为 0 到容器边距的约束的 x 位置将为 8。请注意,这仅适用于 iOS8 或更高版本。

对于不希望他们的约束进入容器边距的每个人:

CTRL+单击+拖动显示约束创建弹出窗口。

如果菜单显示默认创建对边距的约束,请按住 option/alt 以允许对容器而不是容器边距进行约束。

现在它将显示创建约束而不是边缘的选项。这在我的使用中WAY快了。

【讨论】:

这可能是我找到的最好的解决方案。取消选中“限制到边距”并不总是有效,而且感觉有点太神奇了。这是完美的。 为什么默认不是 10pt? Apple 有根据可用性研究选择长度和尺寸的历史,而不是通过选择我们阅读代码的人可能更喜欢的数字。例如。许多事物的默认高度是 44 或 35 pt。 @ZaBlanc 当我在情节提要上添加约束时默认情况下没有边距的完美解决方案。谢谢!

以上是关于什么是 Xcode 6 故事板中的“限制到边距”的主要内容,如果未能解决你的问题,请参考以下文章

如何在 xcode 6.3 界面构建器故事板中默认模拟指标?

XCode故事板中的自定义静态表格单元格?

是否可以在 Xcode 5 中构建 iphoneos6.1 项目,保留 Xcode 4.6.3 故事板中布局的视图行为?

如何更改 Xcode 故事板中的预览设备?

不需要xcode故事板中的大写标签

调整图像大小以适合 xcode 故事板中的 Ui 图像视图