Xcode изменяет неизмененную раскадровку и файлы XIB
Раскадровки - это скорее королевская боль с точки зрения рабочего процесса git, когда над ними сотрудничают несколько человек. Например, XML в файле.storyboard имеет начало <document>
тега toolsVersion
а также systemVersion
атрибуты, измененные в зависимости от конфигурации, в которой работает последний файловый манипулятор. Синхронизация всех версий XCode точно помогает toolsVersion
, но systemVersion
меняется независимо от того, что зависит от конкретной версии Mac и / или OS X, на которой работает разработчик.
Это идиотский, но в основном безобидный. Что нас беспокоит, так это то, что иногда другие изменения автоматически вносятся в раскадровку, просто открывая их после git pull
, То есть Алиса вносит изменения в раскадровку, фиксирует их и помещает в репозиторий. Затем Боб извлекает изменения Алисы и открывает раскадровку, чтобы внести дальнейшие изменения. В тот момент, когда он открывает раскадровку, значок файла немедленно переходит в измененное, но несохраненное состояние, и git status
показывает, что любое количество странных изменений произошло. И все это без того, чтобы Боб ничего не изменил и не сохранил файл сам.
Наиболее распространенное автоматическое изменение, которое мы наблюдаем, - это исчезновение или повторное появление всего <classes>
отметьте иерархию в конце файла раскадровки. Мы не выяснили, что является причиной этого. У нас может быть несколько локализованных версий раскадровки в различных каталогах.lproj, и при открытии их в Интерфейсном Разработчике иерархия классов может самопроизвольно удаляться из одних и добавляться в другие, или оставляться в одних в некоторых. Это вызывает много шума в git diff
, но это на самом деле не нарушает никакой функциональности. Мы часто выборочно добавляем фактические изменения, которые мы внесли в индекс git, фиксируем их, а затем просто отбрасываем спонтанные, бессмысленные <classes>
изменения. Это делается для того, чтобы коммиты были маленькими и красивыми, какими они и должны быть. В конце концов, однако, это становится слишком много, чтобы беспокоиться, так как XCode продолжает пересматривать изменения, и кто-то просто раздражает их коммитом вместе с некоторыми другими вещами... это хорошо, пока XCode другого не решит хотеть изменить их обратно ни за что очевидная причина. (Наша история коммитов много ругается по этому поводу.)
Кто-нибудь еще видит это поведение? Это ошибка XCode или проблема конфигурации на одном или нескольких наших Mac для разработчиков? Мы видели подобное поведение при работе с файлами XIB, но раскадровки кажутся более восприимчивыми к этому.
5 ответов
Это не ошибка, это следствие того, как Xcode обрабатывает файлы раскадровки. Я пишу программу сравнения и слияния для файлов раскадровки (ссылка на GitHub) и провел часы, анализируя логику файлов раскадровки и то, как Xcode обрабатывает ее. Вот что я обнаружил:
Почему в файлах раскадровки происходят странные изменения? Xcode использует API NSXML для разбора файлов раскадровки в некоторые
NSSet
логическая древовидная структура Когда Xcode нужно записать изменения, он создаетNSXMLDocument
на основе структуры логического дерева, очищает файл раскадровки и вызываетXMLDataWithOptions:
заполнить файл снова. Поскольку наборы не сохраняют порядок своих элементов, даже малейшая модификация может изменить весь XML-файл раскадровки.Почему тег класса исчезает или появляется снова случайно?
<class>
раздел не более чем внутренний кеш Xcode. Xcode использует его для кэширования информации о классах. Кеш меняется часто. Элементы добавляются, когда класс.h/.m
файлы открываются и удаляются, когда XCode подозревает, что они устарели (по крайней мере, старые XCode ведут себя так). При сохранении раскадровки текущая версия кэша сбрасывается, поэтому<class>
раздел часто меняется или даже исчезает.
Я не перепроектировал Xcode; Я сделал эти наблюдения, экспериментируя с файлами Xcode и раскадровки. Тем не менее, я почти на 100% уверен, что так работает.
Выводы:
- Раздел кэша не важен; Вы можете спокойно игнорировать любые изменения в нем.
- В отличие от того, что вы можете найти на всех форумах, объединение файлов раскадровок не является сложной задачей. Например, давайте предположим, что вы изменили
MyController1
просмотр контроллера в раскадровке документа. Откройте файл раскадровки и найдите что-то вроде этого<viewController id=”ory-XY-OBM” sceneMemberID=”MyController1”>
, Вы можете безопасно вносить только изменения в этом разделе и игнорировать все остальное. Если вы изменили сегменты или ограничения, также передайте все, что имеет“ory-XY-OBM”
внутри. Просто!
Это ошибка в XCode 4.5+, я надеюсь, что она исправлена, и да, это PITA.
Вот полная ошибка в Apple
Как избежать бесполезного редактирования XCode в файлах раскадровки?
Эта проблема может быть несколько смягчена чрезвычайно разумным использованием git add -p
в любом из сгенерированных файлов Xcode, включая раскадровки, XIB, модели базовых данных и файлы проекта, которые страдают от аналогичных временных изменений, которые не влияют на фактический интерфейс / модель / проект.
Наиболее распространенные нежелательные изменения, которые я видел на раскадровках, - это номера версий системы (как вы упоминаете) и постоянное добавление и удаление <classes>
раздел, упущение которого я никогда не видел, вызывает проблемы. Для XIB это добавление и удаление <reference key="NSWindow"/>
, который даже не класс в Какао Touch. Просто вау.
Думайте об этом как о море: здесь есть и прилив, и отлив. Пусть оно омывает тебя.
Ааа. Вот и все.
Вы можете игнорировать эти изменения при внесении изменений, сбросить ненужные изменения и сделать чистый коммит.
Единственное преимущество, которое я видел с раскадровками по сравнению с XIB с технической точки зрения, заключается в том, что Apple еще не кастрировала FileMerge, чтобы отказаться от объединения конфликтующих раскадровок. (Раньше FileMerge мог объединять XIB, но более новые версии это сломали. Ребята, ххххх!!!)
Пожалуйста, напишите много ошибок обо всех этих проблемах на http://bugreporter.apple.com/! И не забудьте создавать записи на OpenRadar.
Здесь добавлю еще один ответ, потому что ситуация значительно улучшилась. XML для файла XIB, который представляет StoryBoard, был значительно упрощен.
Я также недавно укусил пулю и начал использовать интерфейс в XCode к Source Control. Я был в командной строке в течение многих лет и счастлив там, но интерфейс приятный и позволяет разделять коммиты, что очень важно, если вы используете систему тикетов, которая связывается с коммитами.
Во всяком случае, сегодня я заметил, что на раскадровке произошли изменения, и встроенный diff показал, что это единственный атрибут в теге документа (systemVersion). Так что ничего страшного.
Я читал статьи, где люди говорят, что СБ были запрещены в своих командах из-за проблем слияния. Полное безумие Они настолько удивительны, особенно теперь, когда в них встроена интеллектуальная автоматическая компоновка, вы действительно пропускаете их, если не используете их.
Полезно знать, почему происходит это безумие, но для тех, кто верит в защиту своих проектов от предупреждений и кто просто хочет быстро и грязно вернуть свои проекты в нормальное состояние:
Не совершайте ничего, пока не получите явных указаний.
Откройте Xcode и создайте новую раскадровку (Command+N > iOS > Пользовательский интерфейс> Раскадровка). Я предполагаю, что вы называете это именем по умолчанию
Storyboard.storyboard
,Откройте раскадровку, которую Xcode нарушил. Я предполагаю, что это
Base.lproj/Main.storyboard
,Выберите и скопируйте все на раскадровке (Ctrl +A, затем Ctrl +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's insanity."
Не обращайте внимания на изменения в
project.pbxproj
с помощьюgit checkout -- project.pbxproj
, если тыgit diff
файл, вы увидите, что он только что добавил информацию о нашей временной раскадровке (которая больше не существует).Откройте резервную копию Xcode и увидите, что предупреждения исчезли.
Вдох.
Работа над одной раскадровкой не проблема. Но работа с одним и тем же контроллером представления, который создает конфликты при извлечении / слиянии, пугает. мы действительно не можем избежать этого, работая в одном viewcontroller для большой команды.
Хорошо, что в большинстве случаев мы можем исправить одни и те же конфликты контроллера представления, если понимаем структуру xml. Я ни разу не упустил возможности объединить их, работая в команде. Предположим, вы работаете с контроллером просмотра. Ваш вид в настоящее время пуст. Пожалуйста, посмотрите на xml-структуру viewcontroller из опции исходного кода.
Раскадровка - это xml, ограниченный тегом типа документа. Все в раскадровке содержится в теге sceneID=. Тег сцены содержит все контроллеры просмотра. Это основное.
Теперь мы добавили в представление UILabel и UIButton. Также установите автоматическое размещение элементов. Теперь это выглядит так:
Добавление уровня / кнопки в viewcontroller добавило некоторый новый код внутри тега subview представления. То же самое касается дальнейшего добавления элементов или любых изменений пользовательского интерфейса. Внимательно проверьте структуру тегов, что действительно важно для устранения любых конфликтов.
Теперь мы добавляем еще один viewcontroller в имя раскадровки Homeviewcontroller. Добавление нового контроллера просмотра означает, что он добавляет новую сцену под тегом сцен. Посмотри на это:
На этом этапе мы случайным образом изменим структуру и рассмотрим проблемы / предупреждения. Мы меняем конечный тег метки первого контроллера просмотра и сохраняем файл. Теперь запустите его и посмотрите предупреждение. Ошибка говорит о том, что конечный тег неверен, который создан из строки 23. В строке 23 мы видим, что ограничения метки установлены без конечного тега. Это проблема. Теперь ставим закрывающий тег и строим проект. После установки конечного тега мы можем успешно просмотреть раскадровку.
Если вы столкнетесь с предупреждением о конфликтах, сравните его с предыдущим источником и источником изменений. Мы удаляем старый / избыточный код, оставляем новый код с правильным началом и концом тега и исправляем ошибки.
[NB, я дополню ответ еще несколькими тестовыми случаями, когда получу время]