Интерфейс Builder унифицирует раскадровку, изменяет размеры и виды репозиций с небольшим шагом

У нас есть ряд приложений для iOS, которым способствуют несколько разных разработчиков. Проблема, которую я продолжаю замечать, заключается в том, что представления в наших раскадровках будут смещаться с позиции, в которую они были помещены или изменены, чтобы они были меньше, что на этикетках, размер которых соответствовал тексту, изначально становится болезненно очевидным, когда метки всех внезапно усекают свой текст.

Я замечаю, что эти ухудшения наших представлений отображаются в нашем репозитории Git, когда разработчик напрямую не вносил никаких изменений в раскадровку. Возможно, они просмотрели раскадровку в Interface Builder, но не внесли никаких реальных изменений в раскадровку. Изменения были сохранены и сохранены вместе с тем, над чем они работали.

Когда я делаю сравнение текста между файлами раскадровки до и после ответственных коммитов, я вижу небольшие изменения для просмотра фреймов, например:

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

и

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

и

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

и

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

и

<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"/>

В большинстве случаев числа для размеров кадра изменяются на небольшую сумму, либо целочисленное значение изменяется на одно, либо значение с плавающей запятой усекается или десятичная часть изменяется незначительно.

В других случаях значения меняются на несколько точек, например:

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

и

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

и

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

Обратите внимание, что все эти примерные изменения фрейма были взяты из того же примера commit, когда разработчик не намеревался сделать одно изменение в раскадровке. В XML между двумя версиями файла было 269 различий, и все они были такими незначительными изменениями в размерах или позициях кадра. XML раскадровки составляет ~ 9000 строк.

Кажется, что проблема может иметь какое-то отношение к использованию ИБ чисел с плавающей запятой и ошибок округления, а различия, которые становятся на несколько пикселей, могут быть совокупностью этих ошибок округления в течение нескольких раз, открывая, анализируя и повторная сериализация данных.

Это всего лишь теория, хотя я не смог точно определить причину нежелательных изменений. Часто фиксации вообще не вносят каких-либо существенных изменений в фреймы, только незначительные изменения с плавающей запятой, такие как 446.00000055262581 → 446.00000112002783. Но когда происходят серьезные изменения, они, похоже, происходят в большом количестве.

Комиты, между которыми происходят изменения, также создаются одним и тем же разработчиком, используя ту же версию Xcode и Interface Builder. В этом примере commit, где были сделаны эти данные, тег документа <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"> в обеих версиях файла раскадровки, например.

Кроме того, что я не хочу проверять, чтобы не совершать незначительные или непреднамеренные изменения в файлах раскадровки, я хотел бы сузить, что вызывает эти нежелательные изменения в наших представлениях раскадровки. Если это то, что мы можем избежать, это вызывает проблему, мы можем знать причину.

Update: Как Тим с благодарностью отметил, эта проблема, похоже, вызвана при использовании Interface Builder на экране сетчатки. Все разработчики, которые вызвали эту проблему, имеют сетчатку MacBook Pro. Те из нас, кто не видел сетчатки, не испытывали проблемы.

Ответ 1

Самая интересная подсказка в этой загадке заключается в том, что она кажется особенно плохой, когда вы открываете ту же самую раскадровку на экране Retina, в отличие от дисплея с сетчаткой.

Сначала я шел туда и обратно между 4k iMac и pro-retina Macbook pro и получал большой объем изменений (~ 300 строк изменялись каждый раз).

Затем я просто перетащил окно xcode с моего основного монитора (4k/retina) на мой второй монитор (2560x1440, без сетчатки) - и, хотя окно было того же размера, xcode изменил размер всех элементов и пожаловался на ~ 50 неправильных взглядов. Я переместил его обратно на сетчатку, и около половины "неулокальных" ошибок ушли, но половина осталась. Повторное масштабирование - по вашему мнению - ухудшает базовые данные.

Если у вас несколько разработчиков, работающих в одном файле, это часто случается.

Решение? Вероятно, все это на Apple, чтобы исправить - я не сталкивался с настройками, которые в противном случае смягчили бы его.

Ответ 2

Кажется, это ошибка, связанная с сериализации интерфейса Builder CGFloat. Значения размера и позиции для рамок просмотра - это плавающие точки. Но их значения всегда целые. Внутренняя графическая манипуляция требует, чтобы они были плавающей точкой для работы математики преобразования, но все всегда выражается в терминах округлых значений целых точек.

Когда эти значения с плавающей запятой сериализуются в XML раскадровки, IB часто сериализует значения как целые числа, но иногда сериализует их как числа с плавающей запятой. Я не уверен, почему он принимает решение сделать это таким образом, когда это происходит, но это менее распространено. В моем примере фреймов выше, 3 из значений оказались плавающей точкой, а остальные - целыми числами.

Также в моих примерах часто будет отображаться представление с плавающей запятой, которое будет сериализовано как целое. Вот где я считаю, что ошибка найдена.

Одна вещь, которую я заметил с изменением рамок зрения, они стремились двигаться влево или уменьшаться. Таким образом, значения в основном становятся меньше. Вы можете видеть в примерах, которые я вам предоставил, это наиболее вероятно.

Плавающие точки не имеют точности, чтобы точно выражать целочисленные значения, но точны до нескольких десятичных знаков. Поэтому, в то время как иногда целые числа выражаются так, как в моих примерах, немного выше, чем целочисленное значение (т.е. 384.00001078580522), другие выражаются как несколько ниже, чем целое значение. Здесь пример изменения кадра, который сделал 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"/>

В то время как это конкретное изменение, похоже, напрямую не изменяло значение кадра. Оба числа по существу равны 457. Я думаю, что это происходит, когда этот XML повторно обрабатывается, когда раскадровка снова открывается, это может быть усечение значения 456.99999985252464 и чтение его как 456. Это приводит к тому, что значения становятся постепенно меньше, уменьшая размеры или перемещая положение кадров влево или вверх.

Конечно, это всего лишь теория и не дает оснований для того, почему Interface Builder делает это. Кажется, он начался с недавнего выпуска Xcode 6. Кроме того, он не объясняет, как это произошло с 8 до 7,5 на одном примере или даже в один раз с 274 до 276 в моем последнем примере. Но по большей части большинство изменений, как правило, находятся в нисходящем направлении.

Я записываю ошибку с Apple, чтобы это выглядело.

Ответ 3

У меня может быть ответ на эту проблему. Его менее известная функция открытия приложений в режиме низкого разрешения. У нас недавно возникла аналогичная проблема, в которой представление содержимого ячеек табличного представления имело 0,5 дополнительных для высоты, когда линия разделителя установлена ​​по умолчанию или одиночная. Когда его установить в None, этой проблемы не было. меры 1. Перетащите телевизор по умолчанию в раскадровку. Проверьте высоту представления содержимого ячейки представления таблицы. Это будет 43,5. 2. Установите разделительную линию для представления таблицы в положение "Нет". Просмотр содержимого ячейки меняется на 44.

Теперь закройте Xcode и установите режим Open in Low Resolution в окне Finder Get Info для приложения Xcode. Теперь, если вы выполните те же шаги выше, он покажет высоту представления содержимого для ячейки представления таблицы как 43.

Когда есть разные члены команды, работающие на сетчатке и дисплеях без сетчатки, вы просто получите файлы раскадровки, как измененные только потому, что вы открыли раскадровку на экране сетчатки. Один из способов решения этой проблемы - включить режим Open in Low Resolution и работать. Но тогда он побеждает цель иметь сетчатый дисплей, хотя и лучше, чем раскадровки, отмеченные как измененные, хотя вы ничего не изменили.