Interface Builder 以小增量降低情节提要、调整大小和重新定位视图

Posted

技术标签:

【中文标题】Interface Builder 以小增量降低情节提要、调整大小和重新定位视图【英文标题】:Interface Builder degrades storyboards, resizes and repositions views in small increments 【发布时间】:2014-12-23 06:06:34 【问题描述】:

我们有许多不同的开发者贡献的 ios 应用。我继续注意到的一个问题是,我们故事板中的视图将移出它们放置的位置或调整大小以使其更小,这在原本适合文本大小的标签上变得非常明显,当标签全部突然截断他们的文字。

我注意到当开发人员没有直接对故事板进行任何编辑时,我们的视图的这些退化出现在提交到我们的 Git 存储库中。他们可能已经在 Interface Builder 中查看了故事板,但没有对故事板进行任何真正的更改。尽管如此,这些更改仍会与他们正在处理的内容一起保存并提交。

当我在负责提交之前和之后的情节提要文件之间进行文本比较时,我看到视图框架发生了一些小的变化,例如:

<rect key="frame" x="203" y="8"  />
                             |
                             V
<rect key="frame" x="203" y="7.5"  />

<rect key="frame" x="446.00000170260091" y="7"  />
                      |
                      V
<rect key="frame" x="446" y="7"  />

<rect key="frame" x="364" y="3"  />
                      |
                      V
<rect key="frame" x="363" y="3"  />

<rect key="frame" x="284" y="7"  />
                      |                |
                      V                V
<rect key="frame" x="283" y="7"  />

<rect key="frame" x="384.00001078580522" y="7"  />
                      |                                |
                      V                                V
<rect key="frame" x="383.00000530853856" y="7"  />

在大多数情况下,框架尺寸的数字仅发生少量变化,整数值变化一或浮点值被截断或小数部分发生微小变化。

其他时候,这些值会发生一些变化,例如:

<rect key="frame" x="334" y="3"  />
                      |
                      V
<rect key="frame" x="331" y="3"  />

<rect key="frame" x="251" y="7"  />
                                        |
                                        V
<rect key="frame" x="251" y="7"  />

<rect key="frame" x="478" y="3"  />
                      |                 |
                      V                 V
<rect key="frame" x="475" y="3"  />

请注意,当开发人员不打算对情节提要进行单一更改时,所有这些示例框架更改均来自同一个示例提交。两个版本的文件之间的 XML 有 269 处差异,所有这些差异都是帧大小或位置的细微变化。故事板 XML 约为 9000 行。

似乎这个问题可能与 IB 使用浮点数和舍入误差有关,而偏离几个像素的差异可能是这些舍入误差在几次打开、解析和重新序列化数据。

这只是一个理论,因为我无法查明导致不需要的更改的确切原因。通常提交根本不会对帧进行任何重大更改,只有微不足道的浮点更改,例如 446.00000055262581 -> 446.00000112002783。但是当发生严重的变化时,它们似乎大量发生。

发生更改的提交也是由同一开发人员使用相同版本的 Xcode 和 Interface Builder 进行的。在获取此数据的示例提交中,文档标签在故事板文件的两个版本中都是 &lt;document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6250" systemVersion="14A389" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" initialViewController="JAD-vj-VfC"&gt;

除了确保检查不会对故事板文件提交无关紧要或意外的更改之外,我还想缩小导致我们的故事板视图发生这些不必要更改的原因。如果导致问题的原因是我们可以避免做的事情,我们可以知道原因。

更新: 正如 Tim 乐于指出的那样,这个问题似乎是在视网膜显示器上使用 Interface Builder 时引起的。导致问题的所有开发人员都有视网膜 MacBook Pro。我们这些没有视网膜显示器的人没有遇到过这个问题。

【问题讨论】:

Xcode 9.4.1 仍然损坏。每次打开故事板时,我都会提交数百个差异。 Xcode 11.3.1 - 错误仍然存​​在。 2014-2020 (...) Xcode 在故事板打开后仍会产生大量差异。 【参考方案1】:

这个谜中最有趣的线索是,当你在 Retina 显示器上打开同一个故事板时,它似乎特别糟糕,而不是在非视网膜显示器上。

起初,我在 4k iMac 和 pre-retina Macbook pro 之间来回切换,并且进行了大量更改(每次更改约 300 行)。

然后我只是将 xcode 窗口从我的主显示器 (4k/retina) 拖到我的第二个显示器 (2560x1440, non-retina) - 虽然窗口大小相同,但 xcode 调整了所有元素的大小并抱怨〜 50 错位的意见。我将它移回视网膜显示器,大约一半的“错位”错误消失了,但仍有一半。正如您所建议的那样,重新缩放会降低基础数据的质量。

如果您有多个开发人员在处理同一个文件,这肯定会经常发生。

解决方案?这很可能完全由 Apple 来纠正 - 我没有遇到任何可以缓解它的设置。

【讨论】:

Pradeep K 找到了让 Xcode 忽略 Retina 显示模式***.com/a/36124980/2064473 的设置,尽管正如他所指出的那样,这违背了使用 Retina 显示器的意义。我禁用了该设置,因为无论如何我主要在外部显示器上开发。【参考方案2】:

这似乎是与 Interface Builder 的 CGFloat 值序列化有关的错误。视图框架的大小和位置值是浮点数。但它们的值始终是整数。内部图形操作要求它们是浮点数才能使变换数学起作用,但所有内容始终以整数点值表示。

当这些浮点值被序列化为故事板 XML 时,IB 通常将值序列化为整数,但偶尔也会将它们序列化为浮点数。我不确定为什么它会决定这样做,但它不太常见。在我上面的示例框架中,其中 3 个值最终是浮点数,而其他值是整数。

在我的示例中也可以看到,浮点表示通常会被更改为序列化为整数。这是我认为发现错误的地方。

随着视图框架的变化,我注意到一件事,它们倾向于向左移动或缩小。所以值大多越来越小。您可以在我提供的示例中看到,大多数情况下都是如此。

浮点数没有精确表达整数值的精度,但精确到小数点后几位。因此,虽然有时整数在我的示例中表示为略高于整数值(即 384.00001078580522),但其他整数表示为略低于整数值。以下是 IB 所做的帧更改示例:

<rect key="frame" x="457" y="7"  />
                      |
                      V
<rect key="frame" x="456.99999985252464" y="7"  />

虽然这一特殊更改似乎并未直接修改框架的值。这两个数字基本上等于 457。我认为正在发生的是,当再次打开情节提要时重新解析此 XML 时,它可能会截断 456.99999985252464 值并将其读取为 456。这会导致值逐渐获取更小,缩小尺寸或将框架的位置向左或向上移动。

当然,这只是一个理论,并没有说明 Interface Builder 这样做的原因。它似乎从最近的 Xcode 6 版本开始。此外,它没有解释它是如何在一个示例中从 8 变为 7.5 的,甚至没有解释在我的上一个示例中它是如何从 274 变为 276 的。但在大多数情况下,大部分变化往往是向下的。

我正在向 Apple 提交一个错误以对此进行调查。

【讨论】:

感谢杰夫的冗长解释,这也发生在我们身上。你有什么办法避免这种情况吗? @celiker 正如 Tim 乐于指出的那样,这似乎与在视网膜显示器上使用 Interface Builder 有关。我们遇到的所有导致此问题的开发人员都有视网膜显示器,而我们这些没有视网膜显示器的开发人员则没有遇到问题。内部实现,解析和重写 XML,似乎没有正确处理像素精度。因此,在 Apple 修复此错误之前,目前唯一的解决方法是避免在视网膜显示器上使用 IB。 这仍然让我发疯,使用 Xcode 9.1... 你提交了错误吗?【参考方案3】:

我可能有这个问题的答案。它以低分辨率模式打开应用程序是一个鲜为人知的功能。我们最近遇到了一个类似的问题,其中当分隔线设置为默认或单行时,表格视图单元格的内容视图的高度增加了 0.5。当它设置为 None 时,这个问题就不存在了。 脚步 1. 将默认 TVC 拖到情节提要。检查表格视图单元格内容视图的高度。它将是 43.5。 2. 将表格视图的分隔线设置为无。单元格的内容视图变为 44。

现在退出 Xcode 并在 Xcode 应用程序的 Finder 获取信息窗口中设置以低分辨率打开模式。现在,如果您按照上面相同的步骤操作,它会将表格视图单元格的内容视图的高度显示为 43。

当有不同的团队成员处理视网膜显示器和非视网膜显示器时,您只需将故事板文件修改为修改后的内容,因为您在视网膜显示器中打开了故事板。一种解决方法是打开以低分辨率模式打开并工作。但是,它违背了拥有视网膜显示器的目的,但比将情节提要标记为已修改更好,即使您没有更改任何内容。

【讨论】:

在低分辨率模式下打开 Xcode 8.2.1 然后打开我的故事板文件时,我仍然看到 0.5 的增量。

以上是关于Interface Builder 以小增量降低情节提要、调整大小和重新定位视图的主要内容,如果未能解决你的问题,请参考以下文章

Builder模式 和 Fluent Interface

Builder模式 和 Fluent Interface

Builder模式 和 Fluent Interface

Builder模式 和 Fluent Interface

Builder模式 和 Fluent Interface

Interface builder和iphone sdk