Xcode изменяет немодифицированную раскадровку и XIB файлы

Раскалывание - скорее страшная боль от перспективы рабочего процесса git, когда несколько людей сотрудничают с ними. Например, XML в файле .storyboard имеет свои начальные атрибуты <document> tag toolsVersion и systemVersion, измененные любой конфигурацией, с которой работает последний манипулятор. Синхронизация всех версий Xcode точно помогает с помощью toolsVersion, но systemVersion изменяется независимо от того, что в зависимости от конкретной версии Mac и/или OS X разработчика работает.

Это идиотский, но в основном безвредный. Однако нас беспокоит то, что в другое время некоторые другие изменения автоматически преобразуются в раскадровку, просто открывая их после git pull. То есть Алиса вносит изменения в раскадровку, совершает и толкает их в репозиторий. Затем Боб вытаскивает изменения Алисы и открывает раскадровку, чтобы внести дальнейшие изменения. В тот момент, когда он открывает раскадровку, значок файла немедленно изменяется на измененное, но несохраненное состояние, а git status показывает, что произошло любое количество странных изменений. Все это без того, чтобы Боб ничего не изменил или не сохранил сам файл.

Наиболее распространенным автоматическим изменением, которое мы видим, является исчезновение или повторное появление всего тэга <classes> в иерархии в конце файла раскадровки. Мы не выяснили, что вызывает это. У нас может быть несколько локализованных версий раскадровки в разных каталогах .lproj, и при их открытии внутри Interface Builder иерархия классов может быть спонтанно удалена из некоторых и добавлена ​​в другие или оставлена ​​одна в некоторых. Это вызывает много шума в git diff, но на самом деле он не нарушает никаких функций. Мы часто будем избирательно добавлять фактические изменения, внесенные нами в индекс git, фиксировать их, а затем просто отбрасывать спонтанные, бессмысленные изменения <classes>. Это должно держать мелкие и приятные, как и должно быть. В конце концов, однако, это просто становится слишком много, чтобы беспокоиться, так как Xcode продолжает повторять изменения, а кто-то просто ragecommits их вместе с некоторыми другими вещами... это нормально, пока кто-то еще Xcode не захочет изменить их для no очевидная причина. (Наша история фиксации имеет много ругательств над этим.)

Кто-нибудь еще видит это поведение? Является ли это ошибкой Xcode или проблемой конфигурации на одном или нескольких наших Mac-разработчиков? Мы видели подобное поведение при взаимодействии с XIB файлами, но раскадровки выглядят более восприимчивыми к этому.

Ответ 1

Это не ошибка, это следствие того, как Xcode обрабатывает файлы раскадровки. Я пишу программу diff и merge для файлов раскадровки (ссылка GitHub), и я потратил часы на анализ логики файлов раскадровки и то, как Xcode обрабатывает ее. Это то, что я обнаружил:

  • Почему в файлах раскадровки происходят странные изменения? Xcode использует NSXML API для анализа файлов раскадровки в некоторой логической древовидной структуре на основе NSSet. Когда Xcode необходимо записать изменения, он создает NSXMLDocument на основе логической древовидной структуры, очищает файл раскадровки и вызывает XMLDataWithOptions:, чтобы снова заполнить файл. Поскольку наборы не сохраняют порядок своих элементов, даже малейшая модификация может изменить весь XML файл раскадровки.

  • Почему метка класса исчезает или появляется случайно? Раздел <class> - это не что иное, как внутренний кеш Xcode. Xcode использует его для кэширования информации о классах. Кэш часто меняется. Элементы добавляются, когда файлы класса .h/.m открываются и удаляются, когда Xcode подозревает, что они устарели (по крайней мере, старые Xcodes ведут себя так). Когда вы сохраняете раскадровку, сбрасывается текущая версия кеша, поэтому раздел <class> часто изменяется или даже исчезает.

У меня нет обратного Xcode; Я сделал эти наблюдения, экспериментируя с файлами Xcode и раскадровки. Тем не менее, я почти на 100% уверен, что он работает таким образом.

Выводы

  • Раздел кэша неважен; вы можете спокойно игнорировать любые изменения в нем.
  • В отличие от того, что вы можете найти на всех форумах, слияние файлов раскадровки не является сложной задачей. Например, предположим, что вы изменили контроллер MyController1 в документе раскадровки. Откройте файл раскадровки и найдите что-то вроде этого <viewController id="ory-XY-OBM" sceneMemberID="MyController1">. Вы можете безопасно совершать только изменения в этом разделе и игнорировать все остальное. Если вы изменили segues или ограничения, также совершите все, что имеет "ory-XY-OBM" внутри. Простой!

Ответ 3

Эта проблема может быть смягчена с помощью чрезвычайно разумного использования git add -p для любого из файлов, генерируемых Xcode, включая раскадровки, XIB, модели Core Data и файлы проектов, все из которых страдают от аналогичных переходных изменений, которые не влияют на фактический интерфейс/модель/проект.

Наиболее распространенными изменениями нежелательной почты, которые я видел на раскадровках, являются номера версий системы (как вы упоминаете) и постоянное добавление и удаление раздела <classes>, упущение которого я никогда не видел, вызывает проблемы. Для XIB это добавление и удаление <reference key="NSWindow"/>, которое даже не является классом в Cocoa Touch. Просто ничего себе.

Подумайте об этом, как о море: есть как высокий, так и низкий прилив. Пусть он омывается над вами.

Ааа. Что это.

Вы можете игнорировать эти изменения при постановке изменений, reset изменения мусора и сделать чистую фиксацию.

Единственное преимущество, которое я видел с помощью раскадровки над XIB с технической точки зрения, заключается в том, что Apple еще не кастрировала FileMerge, чтобы отказаться от слияния конфликтующих раскадровки. (FileMerge имел обыкновение объединять XIB, но новые версии нарушили это. спасибоxxx guys 💜!!!)

Пожалуйста, напишите много ошибок обо всех этих проблемах в http://bugreporter.apple.com/! И не забудьте создать записи на OpenRadar.

Ответ 4

Нанесение другого ответа здесь, потому что эта ситуация значительно улучшилась. XML для XIB файла, который представляет StoryBoard, был значительно упрощен.

Я также недавно укусил пулю и начал использовать интерфейс в Xcode для Source Control. Я был в командной строке годами и счастлив там, но интерфейс хорош, и он позволяет разделить фиксации, что очень важно, если вы используете систему билетов, которая ссылается на коммит.

В любом случае, сегодня я заметил, что на раскадровке произошли изменения, а встроенный diff показал, что это единственный атрибут в теге document (systemVersion). Так что неважно.

Я читал статьи, в которых люди говорят, что SBs были объявлены вне закона в своих командах из-за проблем с объединением. Полное безумие. Они настолько удивительны, особенно теперь, когда у них есть интеллектуальная автоматическая автозагрузка, вы действительно упускаете их, если не используете их.

Ответ 5

Полезно знать, почему это безумие происходит, но для тех, кто верит в то, что их проекты свободны от предупреждений и кто просто хочет быстро и грязно вернуть свои проекты в здоровое состояние:

  • Не совершайте ничего, пока явным образом не проинструктирован.

  • Откройте Xcode и создайте новую раскадровку (Command + N > iOS > Пользовательский интерфейs > Раскадровка). Предположим, вы называете это именем по умолчанию Storyboard.storyboard.

  • Откройте раскадровку, нарушенную Xcode. Я предполагаю, что это Base.lproj/Main.storyboard.

  • Выберите и скопируйте все на раскадровке (Command + A, затем Command + C).

  • Откройте Storyboard.storyboard.

  • Скопируйте и вставьте все в Storyboard.storyboard.

  • Закройте Xcode.

  • Откройте терминал и смените каталоги на ваш репозиторий.

  • Замените Main.storyboard на Storyboard.storyboard (mv Storyboard.storyboard Base.lproj/Main.storyboard).

  • git add Base.lproj/Main.storyboard; git commit -m "Fix Xcode insanity."

  • Отмените изменения на project.pbxproj через git checkout -- project.pbxproj. Если вы git diff файл, вы увидите, что он только что добавил информацию о нашей временной раскадровке (которая больше не существует).

  • Откройте резервную копию Xcode и убедитесь, что предупреждения исчезли.

  • Дыши.