简体   繁体   English

Interface Builder会以较小的增量降低故事板,调整视图大小和重新定位视图

[英]Interface Builder degrades storyboards, resizes and repositions views in small increments

We have a number of iOS apps that several different developers contribute to. 我们有许多iOS应用程序,有几个不同的开发人员参与其中。 A problem that I continue to notice is that views in our storyboards will shift out of the position they were put in or resize so that they are smaller, which on labels that were sized to fit text originally becomes painfully obvious when the labels all of a sudden are truncating their text. 我不断注意到的一个问题是,我们的故事板中的视图将移出它们放置的位置或调整大小以使它们更小,在标签尺寸适合文本的标签上最初变得非常明显突然间正在截断他们的文字。

I'm noticing these degradations of our views appear in commits to our Git repository when the developer did not directly make any edits to the storyboard. 当开发人员没有直接对故事板进行任何编辑时,我注意到我们的视图的这些降级出现在我们的Git存储库的提交中。 They may have viewed the storyboard in Interface Builder, but did not make any real changes to the storyboard. 他们可能已经在Interface Builder中查看了故事板,但没有对故事板进行任何真正的更改。 The changes were nevertheless saved and committed along with what they were working on. 然而,这些变化与他们正在进行的工作一起得到了保存和承诺。

When I do a text compare between the storyboard files before and after the responsible commits I see small changes to view frames such as: 当我在负责提交之前和之后进行故事板文件之间的文本比较时,我看到对视图帧的小改动,例如:

<rect key="frame" x="203" y="8" width="362" height="29"/>
                             |
                             V
<rect key="frame" x="203" y="7.5" width="362" height="29"/>

and

<rect key="frame" x="446.00000170260091" y="7" width="302" height="30"/>
                      |
                      V
<rect key="frame" x="446" y="7" width="302" height="30"/>

and

<rect key="frame" x="364" y="3" width="200" height="38"/>
                      |
                      V
<rect key="frame" x="363" y="3" width="200" height="38"/>

and

<rect key="frame" x="284" y="7" width="97" height="30"/>
                      |                |
                      V                V
<rect key="frame" x="283" y="7" width="96" height="30"/>

and

<rect key="frame" x="384.00001078580522" y="7" width="101" height="30"/>
                      |                                |
                      V                                V
<rect key="frame" x="383.00000530853856" y="7" width="100" height="30"/>

Most of the time the numbers for frame dimensions are changing by just a small amount, either an integer value changes by one or a floating point value is truncated or the decimal portion is changed minorly. 大多数情况下,帧维数的数字只会改变一小部分,要么整数值改变一个,要么浮点值被截断,或小数部分稍微改变。

Other times, the values are changing by a few points though like: 其他时候,价值变化了几点,但是:

<rect key="frame" x="334" y="3" width="200" height="38"/>
                      |
                      V
<rect key="frame" x="331" y="3" width="200" height="38"/>

and

<rect key="frame" x="251" y="7" width="223" height="30"/>
                                        |
                                        V
<rect key="frame" x="251" y="7" width="220" height="30"/>

and

<rect key="frame" x="478" y="3" width="274" height="38"/>
                      |                 |
                      V                 V
<rect key="frame" x="475" y="3" width="276" height="38"/>

Note that all of these example frame changes were taken from the same example commit when the developer did not intend to make a single change to the storyboard. 请注意,当开发人员不打算对故事板进行单个更改时,所有这些示例框架更改都取自相同的示例提交。 There were 269 differences in the XML between the two versions of the file, all of them being these slight changes in frame sizes or positions. 两个版本的文件之间的XML有269个差异,所有这些都是帧大小或位置的这些微小变化。 The storyboard XML is ~9000 lines. 故事板XML大约是9000行。

It seems the issue may have something to do with IB's use of floating point numbers and rounding errors and the differences that become off by a few pixels could be an aggregation of these rounding errors over a period of several times opening, parsing and re-serializing the data. 似乎这个问题可能与IB使用浮点数和舍入误差有关,并且几个像素的差异可能是这些舍入错误的聚合,在几次打开,解析和重新序列化的过程中数据。

This is just a theory though as I've not been able to pinpoint the exact cause of the unwanted changes. 这只是一个理论,因为我无法确定不必要的变化的确切原因。 Often commits don't make any significant changes to the frames at all, only insignificant floating point changes such as 446.00000055262581 -> 446.00000112002783. 通常提交根本不对帧进行任何重大更改,只有微不足道的浮点更改,例如446.00000055262581 - > 446.00000112002783。 But when the serious changes occur, they seem to occur in large numbers. 但是当发生严重变化时,它们似乎大量出现。

The commits between which the changes occur are also made by the same developer using the same version of Xcode and Interface Builder too. 发生更改的提交也由同一个开发人员使用相同版本的Xcode和Interface Builder进行。 In this example commit where this data was taken, the document tag is <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"> in both versions of the storyboard file for example. 在此示例中提交此数据的提交,文档标记为<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">在两个版本的情节<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">文件中, <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">

Other than being sure to check not to commit insignificant or unintended changes to storyboard files, I'd like to narrow down what is causing these unwanted changes to our storyboard views. 除了确保检查不对故事板文件进行无意义或无意的更改之外,我还想缩小导致这些不必要的更改到故事板视图的原因。 If it's something we can avoid doing that is causing the issue, we can be aware of the cause. 如果这是我们可以避免这样做导致问题,我们可以知道原因。

Update: As Tim helpfully noted, this issue does seem to be caused while using Interface Builder on a retina display. 更新:正如Tim所说,在视网膜显示器上使用Interface Builder时,似乎确实会出现此问题。 All the developers that have caused the problem have retina MacBook Pros. 引起问题的所有开发人员都拥有视网膜MacBook Pro。 Those of us without retina displays have not experienced the issue. 没有视网膜显示的我们这些人没有遇到过这个问题。

The most interesting clue in this mystery is that it seems especially bad when you open the same storyboard on a Retina display as opposed to a non-retina display. 这个谜中最有趣的线索是,当你在Retina显示屏上打开相同的故事板而不是非视网膜显示器时,它似乎特别糟糕。

At first I was going back and forth between a 4k iMac and a pre-retina Macbook pro and was getting a large volume of changes (~300 lines altered each time). 起初,我在4k iMac和视网膜前Macbook pro之间来回走动,并且进行了大量的更改(每次更改约300行)。

Then I simply dragged the xcode window from my main monitor (4k/retina) over to my second monitor (2560x1440, non-retina) - and while the window was the same size, xcode resized all the elements and complained of ~50 misplaced views. 然后我只是将xcode窗口从我的主显示器(4k /视网膜)拖到我的第二台显示器(2560x1440,非视网膜) - 当窗口大小相同时,xcode调整了所有元素的大小并抱怨了~50个错位的视图。 I moved it back to the retina display and about half of the "misplaced" errors went away, but half remained. 我将它移回视网膜显示器,大约一半“错位”的错误消失了,但一半仍然存在。 The re-scaling - as you suggest - degrades the underlying data. 正如您所建议的那样,重新缩放会降低基础数据。

If you've got multiple developers working on the same file, this is bound to happen frequently. 如果你有多个开发人员在同一个文件上工作,这肯定会经常发生。

The solution? 解决方案? This is likely all on Apple to correct - I haven't run into any settings that would mitigate it otherwise. 这可能是苹果公司要纠正的 - 我没有遇到任何会减轻它的设置。

This seems to be a bug related to Interface Builder's serialization of CGFloat values. 这似乎是与Interface Builder的CGFloat值序列化相关的错误。 The size and position values for view frames are floating points. 视图框的大小和位置值是浮点。 But their values are always integers. 但他们的价值观总是整数。 The internal graphic manipulation requires them to be floating point for the transform math to work, but everything is always expressed in terms of round integer point values. 内部图形操作要求它们是浮点,以使变换数学运行,但所有内容始终以圆整数点值表示。

When these floating point values are serialized to the storyboard XML, IB often serializes the values as integers, but occasionally serializes them as floating point numbers too. 当这些浮点值序列化到故事板XML时,IB通常将值序列化为整数,但偶尔也将它们序列化为浮点数。 I'm not sure why it makes the decision to do it this way when it does, but it's less common. 我不确定为什么它决定这样做,但它不太常见。 In my example frames above, 3 of the values ended up being floating point, while the others are integers. 在我上面的示例框架中,其中3个值最终为浮点数,而其他值为整数。

Also seen in my examples, often the floating point representation will be changed to be serialized as an integer instead. 在我的例子中也可以看到,浮点表示通常会被改为序列化为整数。 This is where I believe the bug is found. 这是我相信找到错误的地方。

One thing I noticed with the way view frames were changing, they were tending to move to the left or shrink in size. 有一件事我注意到视图框架的变化方式,它们倾向于向左移动或缩小尺寸。 So the values are mostly getting smaller. 因此价值观大多变小。 You can see in the examples I provided, this is most always the case. 您可以在我提供的示例中看到,这种情况总是如此。

Floating points don't have the precision to express integer values exactly, but are accurate out to several decimal places. 浮点没有精确表达整数值的精度,但精确到几个小数位。 So while sometimes integers are expressed as those in my examples as slightly higher than the integer value (ie 384.00001078580522), others are expressed as slightly lower than the integer value. 因此,虽然有时整数在我的示例中表示为略高于整数值(即384.00001078580522),但其他整数表示为略低于整数值。 Here's an example of a frame change that IB made: 以下是IB制作的帧更改示例:

<rect key="frame" x="457" y="7" width="291" height="30"/>
                      |
                      V
<rect key="frame" x="456.99999985252464" y="7" width="291" height="30"/>

While this particular change didn't seem to modify the frame's value directly. 虽然这种特殊的变化似乎并没有直接修改框架的价值。 Both numbers are essentially equal to 457. What I think is occurring is when this XML is re-parsed when the storyboard is opened again, it could be truncating the 456.99999985252464 value and reading it as 456. This is then causing the values to get progressively smaller, shrinking the sizes or shifting the position of the frames to the left or up. 这两个数字基本上等于457.我认为发生的是当故事板再次打开时重新解析此XML时,它可能会截断456.99999985252464值并将其读取为456.这会导致值逐渐增加更小,缩小尺寸或将框架的位置向左或向上移动。

Of course this is just a theory and doesn't give a reason for why Interface Builder is doing this. 当然,这仅仅是一个理论,并没有给出Interface Builder为什么这样做的原因。 It seems to have begun since the recent Xcode 6 release. 它似乎从最近的Xcode 6发布开始。 Also, it doesn't explain how it went from 8 to 7.5 on one example or even the one time it went from 274 to 276 in my last example. 此外,它没有解释它是如何在一个例子中从8变为7.5,或者甚至在我的上一个例子中从274变为276的一次。 But for the most part, most of the changes tend to be in the downward direction. 但在大多数情况下,大多数变化往往是向下的方向。

I'm filing a bug with Apple to have this looked into. 我正在向Apple提交一个错误,以便对此进行调查。

I might have an answer to this problem. 我可能会对这个问题有一个答案。 Its a lesser know feature of opening the apps in low resolution mode. 它是在低分辨率模式下打开应用程序的一个鲜为人知的功能。 We recently had a similar problem wherein the content view of the table view cells had a 0.5 extra for the height when the separator line is set to default or single. 我们最近遇到了类似的问题,其中当分隔线设置为默认值或单个时,表格视图单元格的内容视图的高度为0.5。 When its set to None then this problem was not there. 当它设置为None时,那个问题就不存在了。 Steps 1. Drag a default TVC to storyboard. 步骤1.将默认TVC拖到故事板。 Check the height of the content view of the table view cell. 检查表视图单元格的内容视图的高度。 It will be 43.5. 这将是43.5。 2. Set the separator line for the table view to None. 2.将表视图的分隔线设置为“无”。 The content view of the cell changes to 44. 单元格的内容视图更改为44。

Now quit Xcode and set the Open in Low Resolution mode in Finder Get Info window for the Xcode app. 现在退出Xcode并在Xcode应用程序的Finder Get Info窗口中设置Open in Low Resolution模式。 Now if you follow the same steps above it will show the height of the content view for table view cell as 43. 现在,如果您按照上面的相同步骤操作,它将显示表视图单元格的内容视图的高度为43。

When there are different team members working on retina and non-retina displays you would simply get the storyboard files as modified just because you opened the storyboard in retina display. 当有不同的团队成员在视网膜和非视网膜显示器上工作时,您只需将故事板文件修改为仅因为您在视网膜显示器中打开故事板。 One workaround for this is to turn the Open in Low Resolution mode and work. 一种解决方法是在低分辨率模式下打开并工作。 But then it defeats the purpose of having a retina display though but better than having storyboards marked as modified even though you have not changed anything. 但是它失败了显示视网膜显示的目的,但比将故事板标记为修改更好,即使你没有改变任何东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM