Xcode zmienia niezmodyfikowane pliki scenorysu i XIB


133

Storyboardy są raczej królewskim bólem z perspektywy przepływu pracy git, gdy współpracuje nad nimi wiele osób. Na przykład XML w pliku .storyboard ma swój początkowy <document>znacznik toolsVersioni systemVersionatrybuty zmienione przez dowolną konfigurację, w której działa najnowszy manipulator plików. Synchronizacja wszystkich wersji Xcode wydaje się pomagać toolsVersion, ale systemVersionzmienia się bez względu na to, w zależności od konkretnej wersji Mac i / lub OS X, na której działa programista.

To idiotyczne, ale w większości nieszkodliwe. Martwi nas jednak to, że w innych przypadkach niektóre inne zmiany są automatycznie wprowadzane do scenorysu, po prostu otwierając je po pliku git pull. Oznacza to, że Alicja wprowadza zmiany w scenorysie, zatwierdza je i wypycha do repozytorium. Następnie Bob pobiera zmiany Alice i otwiera scenorys, aby wprowadzić dalsze zmiany. W momencie, gdy otwiera scenorys, ikona pliku natychmiast zmienia się w zmodyfikowany, ale niezapisany stan, a ikona git statuspokazuje, że nastąpiła dowolna liczba dziwnych zmian. Wszystko to bez konieczności zmiany przez Boba lub samodzielnego zapisania pliku.

Najczęstszą automatyczną zmianą, którą widzimy, jest zniknięcie lub ponowne pojawienie się całej <classes>hierarchii tagów pod koniec pliku storyboardu. Nie ustaliliśmy, co to powoduje. Możemy mieć kilka zlokalizowanych wersji scenorysu w różnych katalogach .lproj, a po otwarciu ich w programie Interface Builder hierarchia klas może zostać spontanicznie usunięta z niektórych i dodana do innych lub pozostawiona sama w niektórych. Powoduje to dużo hałasu git diff, ale w rzeczywistości nie psuje żadnej funkcjonalności. Często będziemy selektywnie dodawać rzeczywiste zmiany, które wprowadziliśmy do indeksu gita, zatwierdzać je, a następnie po prostu odrzucać spontaniczne, bezsensowne<classes>zmiany. Ma to na celu zachowanie niewielkich i ładnych zatwierdzeń, tak jak powinny. W końcu jednak staje się to zbyt trudne, ponieważ Xcode nieustannie odtwarza zmiany, a ktoś po prostu raguje je wraz z innymi rzeczami ... co jest w porządku, dopóki czyjś Xcode nie zdecyduje się na zmianę z powrotem na nie pozorny powód. (W naszej historii zmian jest wiele przekleństw).

Czy ktoś jeszcze widzi takie zachowanie? Czy jest to błąd Xcode lub problem z konfiguracją na co najmniej jednym z naszych komputerów Mac dla programistów? Widzieliśmy podobne zachowanie podczas współpracy z plikami XIB, ale scenorysy wydają się na to bardziej podatne.


Rzeczywiście, projekty Xcode i Git nie radzą sobie zbyt dobrze razem. Nie sądzę, aby można było uniknąć tego bałaganu w inny sposób niż odrzucenie niepotrzebnych zmian - to prawie zawsze zmiany w plikach projektu i innych plikach xml. Jestem pewien, że nie zmieniłem. Będzie zadowolony, jeśli jest jakieś „rozwiązanie”. Podoba mi się Perforce ze względu na wygodną funkcję blokowania, która nie pozwala Xcode na zbyt dużą zmianę, co prawdopodobnie można zrobić ręcznie dla plików, których nie zamierzasz zmieniać, a jedynie przeglądać.
A-Live

3
Nie warto używać storyboardów z gitem ani czymkolwiek innym. Nie są zaprojektowane tak, aby były przyjazne dla popełnienia. Zrezygnowaliśmy i zdecydowaliśmy się na .xib, który też nie jest zbyt dobry, ale przynajmniej jest ziarnisty.
ahwulf

Znaleźliśmy storyboardy całkiem fajne dla wielu rzeczy, chociaż często konieczne jest połączenie ich z XIBami. Jeśli ten błąd kiedykolwiek zostanie naprawiony, będziemy bardzo zadowoleni z pracy z nimi przez większość czasu.
JK Laiho

Muszę tylko skomentować komentarz ahwulfa: co, u licha, masz na myśli, że nie są przyjazne? Są to pliki XML / tekstowe, które są tak przyjazne dla zatwierdzania, jak tylko możesz. I nie miałem problemu z storyboardem i systemem wersjonowania, jedynym problemem jest oczywiście to, że xcode czasami usuwa tag <classes>, a następnie czyta go później, ale możesz to łatwo zobaczyć, jeśli spojrzysz na zmiany za pomocą GUI git lub git -p lub odpowiednik dla dowolnego dvcs. Nigdy nie zdarzyło mi się to z plikiem .pbxproj jako fyi.
mgrandi

Nie rozumiem, dlaczego xcode umieścił bloki klas w scenorysie, skoro może po prostu wygenerować te bloki, czytając pliki klas? czy są one rodzajem „pamięci podręcznej”? jeśli tak, należy je umieścić w pliku classes.cache, abyśmy mogli wykluczyć go z wersjonowania ...
hariseldon78

Odpowiedzi:


79

To nie jest błąd, jest to konsekwencja tego, jak Xcode przetwarza pliki scenorysów. Piszę program do porównywania i scalania plików scenorysów (łącze GitHub) i spędziłem godziny na analizowaniu logiki plików scenorysów i sposobu, w jaki Xcode je przetwarza. Oto, co odkryłem:

  • Dlaczego w plikach scenorysu zachodzą dziwne zmiany? Xcode używa interfejsu API NSXML do analizowania plików scenorysu w NSSetlogicznej strukturze drzewa. Kiedy Xcode musi zapisać zmiany, tworzy w NSXMLDocumentoparciu o logiczną strukturę drzewa, czyści plik storyboardu i wzywa XMLDataWithOptions:do ponownego wypełnienia pliku. Ponieważ zestawy nie zachowują kolejności swoich elementów, nawet najmniejsza modyfikacja może zmienić cały plik XML storyboardu.

  • Dlaczego tag klasy znika lub pojawia się losowo? <class>Sekcja nie jest niczym więcej niż wewnętrznej pamięci podręcznej Xcode. Xcode używa go do buforowania informacji o klasach. Pamięć podręczna często się zmienia. Elementy są dodawane, gdy .h/.mpliki klas są otwierane i usuwane, gdy Xcode podejrzewa, że ​​są nieaktualne (przynajmniej starsze Xcodes zachowują się w ten sposób). Po zapisaniu storyboardu aktualna wersja pamięci podręcznej jest zrzucana, dlatego <class>sekcja często się zmienia lub nawet znika.

Nie poddałem inżynierii wstecznej Xcode; Dokonałem tych obserwacji, eksperymentując z plikami Xcode i storyboardami. Mimo to jestem prawie w 100% pewien, że działa w ten sposób.

Wnioski :

  • Sekcja pamięci podręcznej jest nieważna; możesz bezpiecznie zignorować każdą jego zmianę.
  • W przeciwieństwie do tego, co można znaleźć na wszystkich forach, scalanie plików storyboardów nie jest skomplikowanym zadaniem. Na przykład załóżmy, że zmieniłeś MyController1kontroler widoku w dokumencie serii ujęć. Otwórz plik storyboardu i znajdź coś takiego <viewController id=”ory-XY-OBM” sceneMemberID=”MyController1”>. Możesz bezpiecznie zatwierdzać tylko zmiany w tej sekcji i ignorować wszystko inne. Jeśli zmieniłeś ścieżki lub ograniczenia, zatwierdź także wszystko, co ma w “ory-XY-OBM”środku. Prosty!

9
Jakieś aktualizacje dotyczące narzędzia porównywania / scalania xcode? Wygląda na to, że będzie to bardzo przydatne dla tej społeczności.
Tony

1
Możesz pobrać aplikację z mojej strony internetowej (patrz profil). Aplikacja jest w 100% darmowa.
Marcin Oławski

1
Dla mnie dzielenie storyboardów tak często, jak to możliwe == przy użyciu XIBów. Jeśli chcesz mieć wszystko pokrojone, łatwiej i lepiej korzystać z XIBów
Marcin

7
„Nie poddałem inżynierii wstecznej Xcode; dokonałem tych obserwacji, eksperymentując z plikami Xcode i scenorysami”. To jest (płytka) inżynieria wsteczna i jest fajnie . :-)
Constantino Tsarouhas

14
„To nie jest błąd, to konsekwencja tego, jak Xcode przetwarza pliki storyboardów”. Z całym szacunkiem, druga połowa tego zdania w żaden sposób nie wyjaśnia ani nie racjonalizuje pierwszej. Poprawiłbym to na: „To jest błąd. Jest to [niestety nierozwiązana i bardzo denerwująca] konsekwencja tego, jak XCode przetwarza pliki .xib”. Od XCode 5.x do 6.2 (obecnie 150311) pliki .xib w żaden sposób modyfikowane przez programistę, a jedynie oglądane w IB, ulegają nieuzasadnionym zmianom XML. Jest to poważny błąd, który wpływa na produktywność. Odpowiedzi typu „NBD, po prostu rozdaj fragmenty w gicie” pozostawiają mnie bez słowa.
tydzień

18

To jest błąd w XCode 4.5+, mam nadzieję, że zostanie naprawiony i tak, to PITA.

Oto pełny błąd w Apple

Jak uniknąć nieuzasadnionych zmian w plikach scenorysów w Xcode?


1
To samo w 4.6. Może to nie jest błąd.
Thromordyn

4.6.3 nadal go ma. Nie mogę powiedzieć, że storyboard / xibs kiedykolwiek działały dobrze
houbysoft

1
„To nie jest błąd, to funkcja”: -S
MrTJ

Nie ma dowodów, że jest to błąd - an tak kłopot, ale może to być po prostu jak Xcode robi rzeczy
Thomas Watson

1
7.0.1 nie przyniósł żadnych zmian w tym zakresie.
Andris Zalitis

11

Ten problem można nieco złagodzić przez niezwykle rozsądne użycie git add -pdowolnego z wygenerowanych plików Xcode, w tym scenorysów, XIB, modeli danych podstawowych i plików projektów, z których wszystkie cierpią z powodu podobnych przejściowych modyfikacji, które nie mają wpływu na rzeczywisty interfejs / model / projekt.

Najczęstsze śmieciowe zmiany, jakie widziałem w scenorysach, to numery wersji systemu (jak wspomniałeś) oraz ciągłe dodawanie i usuwanie <classes>sekcji, której pominięcie nigdy nie powodowało problemów. W przypadku XIB jest to dodawanie i usuwanie <reference key="NSWindow"/>, co nie jest klasą w Cocoa Touch. Po prostu wow.

Pomyśl o tym jak o morzu: jest zarówno przypływ, jak i odpływ. Niech cię obmyje.

Ahh. Otóż ​​to.

Możesz zignorować te modyfikacje podczas przemieszczania zmian, zresetować niepotrzebne zmiany i dokonać czystego zatwierdzenia.

Jedyną zaletą, jaką widziałem w przypadku scenorysów nad XIB z technicznego punktu widzenia, jest to, że Apple nie zneutralizował jeszcze FileMerge, aby odmówić scalenia konfliktowych scenariuszy. (FileMerge mógł łączyć pliki XIB, ale nowsze wersje to zepsuły. Thxxxx guys 💜 !!!)

Prosimy o zgłaszanie wielu błędów dotyczących wszystkich tych problemów na stronie http://bugreporter.apple.com/ ! I nie zapomnij utworzyć wpisów w OpenRadar .


6

Dorzucam tutaj inną odpowiedź, ponieważ sytuacja znacznie się poprawiła. XML dla pliku XIB, który reprezentuje StoryBoard, został znacznie uproszczony.

Niedawno też ugryzłem kulę i zacząłem używać interfejsu w Xcode do kontroli źródła. Jestem w wierszu poleceń od lat i jestem szczęśliwy, ale interfejs jest fajny i pozwala na dzielenie zatwierdzeń, co jest naprawdę ważne, jeśli używasz systemu biletowego, który łączy się z zatwierdzeniami.

W każdym razie zauważyłem dzisiaj, że nastąpiła zmiana w scenorysie, a wbudowana różnica pokazała mi, że był to pojedynczy atrybut w tagu dokumentu (systemVersion). Więc nie jest to wielka sprawa.

Czytałem artykuły, w których ludzie twierdzą, że SB zostali wyjęci spod prawa w ich zespołach z powodu problemów z łączeniem. Całkowite szaleństwo. Są tak niesamowite, zwłaszcza teraz, gdy mają wbudowany inteligentny układ, więc naprawdę tracisz, jeśli ich nie używasz.


3

Warto wiedzieć, dlaczego dzieje się to szaleństwo, ale dla tych, którzy wierzą, że ich projekty są wolne od ostrzeżeń i chcą po prostu szybko i bezmyślnie przywrócić swoje projekty do zdrowego stanu:

  1. Nie popełniaj niczego, dopóki nie zostanie to wyraźnie pouczone.

  2. Otwórz Xcode i utwórz nową scenorys (Command + N> iOS> Interfejs użytkownika> Storyboard). Zakładam, że nazwiesz to domyślną nazwą Storyboard.storyboard.

  3. Otwórz scenorys, który naruszył Xcode. Zakładam, że tak Base.lproj/Main.storyboard.

  4. Zaznacz i skopiuj wszystko w serii ujęć (Command + A, a następnie Command + C).

  5. Otwórz Storyboard.storyboard.

  6. Skopiuj i wklej wszystko do Storyboard.storyboard.

  7. Zamknij Xcode.

  8. Otwórz terminal i zmień katalogi w swoim repozytorium.

  9. Zastąpić Main.storyboardw Storyboard.storyboard( mv Storyboard.storyboard Base.lproj/Main.storyboard).

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

  11. Zignoruj ​​zmiany w project.pbxprojza pośrednictwem git checkout -- project.pbxproj. Jeśli znajdziesz git diffplik, zobaczysz, że właśnie dodał informacje o naszej tymczasowej planszy (która już nie istnieje).

  12. Otwórz kopię zapasową Xcode i zobacz, że ostrzeżenia zniknęły.

  13. Oddychać.


0

Praca nad tym samym scenorysem nie stanowi problemu. Ale praca z tym samym kontrolerem widoku, który tworzy konflikty przy ściąganiu / scalaniu, jest przerażająca. nie możemy uniknąć pracy w tym samym kontrolerze widoku dla dużego zespołu.

Dobrze, że w większości przypadków możemy naprawić te same konflikty kontrolera widoku, jeśli zrozumiemy strukturę xml. Nigdy nie zawiodłem się w ich połączeniu podczas pracy w zespole. Załóżmy, że pracujesz z kontrolerem widoku. Twój widok jest obecnie pusty. Proszę spojrzeć na strukturę XML Viewcontrollera z opcji kodu źródłowego.

wprowadź opis obrazu tutaj

Storyboard to XML ograniczony tagiem typu dokumentu. Wszystko w serii ujęć zawiera tag sceny sceneID =. tag sceny zawiera wszystkie kontrolery widoku. To podstawa.

Teraz dodaliśmy do widoku UILabel i UIButton. Ustaw także autoukład elementów. Teraz wygląda to tak:

wprowadź opis obrazu tutaj

Dodanie poziomu / przycisku do kontrolera widoku dodało nowy kod wewnątrz tagu subview widoku. To samo dotyczy dalszego dodawania elementów lub zmian interfejsu użytkownika. Dokładnie sprawdź strukturę tagów, która jest naprawdę ważna, aby naprawić wszelkie konflikty.

Teraz dodajemy kolejny kontroler widoku w nazwie scenorysu Homeviewcontroller. Dodanie nowego kontrolera widoku oznacza dodanie nowej sceny pod tagiem scen. Spójrz na to:

wprowadź opis obrazu tutaj

W tym momencie losowo zmienimy strukturę i będziemy obserwować problemy / ostrzeżenia. Zmieniamy pierwszy tag końcowy etykiety viewcontroller i zapisujemy plik. Teraz uruchom go i spójrz na ostrzeżenie. Błąd mówi, że znacznik końcowy jest nieprawidłowy, który został utworzony z wiersza 23. W wierszu 23 widzimy, że ograniczenia etykiety są ustawione bez znacznika końcowego. To jest problem. Teraz umieszczamy tag końcowy i budujemy projekt. Po ustawieniu tagu końcowego możemy pomyślnie wyświetlić storyboard.

wprowadź opis obrazu tutaj

Gdy napotkasz jakiekolwiek ostrzeżenie o konfliktach, porównaj z poprzednim źródłem i zmienia źródło. Usuwamy stary / nadmiarowy kod, zachowujemy nowy kod z odpowiednim początkiem i końcem tagu i naprawiamy wszystko.

[Uwaga: zaktualizuję odpowiedź o więcej przypadków testowych, gdy otrzymam czasy]

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.