Xcode modifie le storyboard et les fichiers XIB non modifiés

132

Les storyboards sont plutôt une douleur royale du point de vue du flux de travail git lorsque plusieurs personnes collaborent dessus. Par exemple, le XML dans le fichier .storyboard a sa <document>balise de départ toolsVersionet ses systemVersionattributs modifiés par la configuration exécutée par le manipulateur de fichier le plus récent. Synchroniser les versions Xcode de tout le monde semble aider avec précision toolsVersion, mais systemVersionchange quoi qu'il en soit, en fonction de la version Mac et / ou OS X spécifique que le développeur utilise.

C'est idiot, mais surtout inoffensif. Ce qui nous inquiète, cependant, c'est qu'à d'autres moments, d'autres modifications sont automatiquement apportées au storyboard simplement en les ouvrant après un git pull. C'est-à-dire qu'Alice apporte des modifications à un storyboard, les valide et les pousse vers le référentiel. Bob récupère ensuite les modifications d'Alice et ouvre le storyboard pour apporter d'autres modifications. Au moment où il ouvre le storyboard, l'icône du fichier passe immédiatement à un état modifié mais non enregistré, et git statusindique qu'un certain nombre de changements étranges se sont produits. Tout cela sans que Bob n'ait rien changé ou sauvegardé le fichier lui-même.

Le changement automatisé le plus courant que nous constatons est la disparition ou la réapparition de l'ensemble de la <classes>hiérarchie des balises vers la fin d'un fichier de storyboard. Nous n'avons pas compris ce qui cause cela. Nous pouvons avoir plusieurs versions localisées d'un storyboard dans divers répertoires .lproj, et lors de leur ouverture dans Interface Builder, la hiérarchie des classes peut être spontanément supprimée de certains et ajoutée à d'autres, ou laissée seule dans certains. Cela provoque beaucoup de bruit git diff, mais cela n'interrompt aucune fonctionnalité. Nous ajouterons souvent de manière sélective les modifications réelles que nous avons apportées à l'index de git, les commettrons, puis rejetons simplement les modifications spontanées et absurdes<classes>changements. C'est pour garder les commits petits et gentils, comme ils devraient l'être. Finalement, cependant, cela devient tout simplement trop dérangeant puisque Xcode continue de refaire les modifications, et quelqu'un les remet simplement avec d'autres choses ... ce qui est bien jusqu'à ce que Xcode de quelqu'un d'autre décide de vouloir les changer pour non raison apparente. (Notre histoire de commit a beaucoup de jurons à ce sujet.)

Quelqu'un d'autre voit-il ce comportement? S'agit-il d'un bogue Xcode ou d'un problème de configuration sur un ou plusieurs de nos Mac développeurs? Nous avons constaté un comportement similaire lors de la collaboration avec des fichiers XIB, mais les storyboards semblent plus sensibles à cela.

JK Laiho
la source
En effet, les projets Xcode et Git ne fonctionnent pas très bien ensemble. Je ne pense pas que vous puissiez éviter ce désordre autrement que de rejeter les modifications qui sont inutiles - qui sont presque toujours les modifications des fichiers de projet pour moi et d'autres fichiers XML, je suis sûr que je n'ai pas changé. Sera heureux s'il y a une sorte de «solution». J'aime Perforce pour sa fonctionnalité de verrouillage pratique ne permettant pas à Xcode de trop changer, cela pourrait probablement être fait manuellement pour les fichiers que vous n'allez pas modifier mais uniquement pour les examiner.
A-Live
3
Cela ne vaut pas la peine d'utiliser des storyboards avec git ou autre chose. Ils ne sont pas conçus pour être conviviaux. Nous avons abandonné et sommes allés avec .xib qui n'est pas si génial non plus mais au moins c'est granulaire.
ahwulf
En fait, nous avons trouvé des story-boards assez intéressants pour beaucoup de choses, bien qu'il soit souvent nécessaire de les mélanger avec des XIB. Si ce bogue était résolu, nous serions très heureux de travailler avec eux la grande majorité du temps.
JK Laiho
Je dois juste commenter le commentaire d'Ahwulf: qu'est-ce que vous voulez dire par le fait qu'ils ne sont pas amicaux? Ce sont des fichiers XML / texte, qui sont à peu près aussi conviviaux que possible. Et je n'ai eu aucun problème avec le storyboard et un système de versionnage, le seul problème est bien sûr que xcode supprime parfois la balise <classes> puis la lit plus tard, mais vous pouvez le voir facilement si vous regardez les changements avec une interface graphique git ou git -p ou équivalent pour n'importe quel dvcs. Je n'ai jamais eu cela se produire avec le fichier .pbxproj en tant que fyi.
mgrandi
Je ne peux pas comprendre pourquoi xcode a mis les blocs de classes dans le storyboard s'il peut simplement générer ces blocs en lisant les fichiers de classes? sont-ils une sorte de "cache"? si c'est le cas, ils doivent être placés dans un fichier classes.cache afin que nous puissions l'exclure du
contrôle de

Réponses:

78

Ce n'est pas un bogue, c'est une conséquence de la façon dont Xcode traite les fichiers de storyboard. J'écris un programme de comparaison et de fusion pour les fichiers de storyboard (lien GitHub) et j'ai passé des heures à analyser la logique des fichiers de storyboard et comment Xcode les traite. Voici ce que j'ai découvert:

  • Pourquoi des changements étranges se produisent-ils dans les fichiers de storyboard? Xcode utilise l'API NSXML pour analyser les fichiers de storyboard dans une NSSetstructure arborescente logique basée. Lorsque Xcode a besoin d'écrire des modifications, il crée un NSXMLDocumentfichier basé sur l'arborescence logique, efface le fichier de storyboard et appelle XMLDataWithOptions:à nouveau le remplissage du fichier. Étant donné que les ensembles ne conservent pas l'ordre de leurs éléments, même la moindre modification pourrait changer l'ensemble du fichier XML du storyboard.

  • Pourquoi la balise de classe disparaît-elle ou réapparaît-elle au hasard? La <class>section n'est rien de plus qu'un cache Xcode interne. Xcode l'utilise pour mettre en cache des informations sur les classes. Le cache change souvent. Des éléments sont ajoutés lorsque les .h/.mfichiers de classe sont ouverts et supprimés lorsque Xcode suspecte qu'ils sont obsolètes (au moins les anciens Xcodes se comportent comme ceci). Lorsque vous enregistrez le storyboard, la version actuelle du cache est vidée, c'est pourquoi la <class>section change souvent, voire disparaît.

Je n'ai pas de Xcode rétro-ingénierie; J'ai fait ces observations en expérimentant avec des fichiers Xcode et storyboard. Néanmoins, je suis presque sûr à 100% que cela fonctionne de cette façon.

Conclusions :

  • La section Cache n'a pas d'importance; vous pouvez ignorer en toute sécurité tout changement.
  • Contrairement à ce que vous pouvez trouver sur tous les forums, fusionner des fichiers de storyboards n'est pas une tâche compliquée. Par exemple, supposons que vous ayez changé le MyController1contrôleur de vue dans un document de storyboard. Ouvrez le fichier de storyboard et trouvez quelque chose comme ça <viewController id=”ory-XY-OBM” sceneMemberID=”MyController1”>. Vous ne pouvez valider en toute sécurité que les modifications de cette section et ignorer tout le reste. Si vous avez changé de segues ou de contraintes, validez également tout ce qui s'y trouve “ory-XY-OBM”. Facile!
Marcin Olawski
la source
9
Une mise à jour sur l'outil de diff / fusion xcode? On dirait que ce sera super utile pour cette communauté.
Tony
1
Vous pouvez obtenir l'application depuis ma page Web (voir profil). L'application est 100% gratuite.
Marcin Olawski
1
Pour moi, diviser autant que possible les storyboards == en utilisant des XIB. Si vous voulez que tout soit tranché, il est plus facile et meilleur d'utiliser les XIB
Marcin Olawski
7
"Je n'ai pas procédé à une ingénierie inverse de Xcode; j'ai fait ces observations en expérimentant avec Xcode et des fichiers de storyboard." C'est (peu profonde) l' ingénierie inverse, et il est frais . :-)
Constantino Tsarouhas
13
"Ce n'est pas un bug, c'est une conséquence de la façon dont Xcode traite les fichiers de storyboard." Respectueusement, la 2ème moitié de cette phrase n'explique ni ne rationalise en aucune manière la première. Je le modifierais comme suit: "C'est un bogue. C'est une conséquence [malheureusement non résolue et très ennuyeuse] de la façon dont XCode traite les fichiers .xib." De XCode 5.x à 6.2 (aujourd'hui, 150311), les fichiers .xib en aucun cas modifiés par le développeur, simplement visualisés dans IB, subissent des modifications XML gratuites. C'est un bug grossier qui a un impact sur la productivité. Les réponses comme "NBD, juste traiter avec des morceaux dans git" me laissent sans voix.
tous les
18

C'est un bogue dans XCode 4.5+, j'espère qu'il sera corrigé, et oui c'est un PITA.

Voici le bug complet chez Apple

Comment éviter les modifications gratuites de Xcode sur les fichiers de storyboard?

utilisateur supprimé
la source
1
Même chose en 4.6. Ce n'est peut-être pas un bug.
Thromordyn
4.6.3 l'a toujours. Je ne peux pas dire que le storyboard / xibs ait jamais bien fonctionné
houbysoft
1
"Ce n'est pas un bug, c'est une fonctionnalité": -S
MrTJ
Il n'y a aucune preuve qu'il s'agit d'un bogue - un ennui oui, mais c'est peut-être simplement la façon dont Xcode fait les choses
Thomas Watson
1
7.0.1 n'a apporté aucun changement à cela.
Andris Zalitis
11

Ce problème peut être quelque peu atténué par une utilisation extrêmement judicieuse de l' git add -pun des fichiers générés par Xcode, y compris les storyboards, les XIB, les modèles de données de base et les fichiers de projet, qui souffrent tous de modifications transitoires similaires qui n'ont aucun impact sur l'interface / le modèle / projet.

Les changements indésirables les plus courants que j'ai vus sur les storyboards sont les numéros de version du système (comme vous le mentionnez) et l'ajout et la suppression constants de la <classes>section, dont je n'ai jamais vu l'omission causer des problèmes. Pour les XIB, c'est l'ajout et la suppression de <reference key="NSWindow"/>, qui n'est même pas une classe dans Cocoa Touch. Juste wow.

Pensez-y comme à la mer: il y a à la fois une marée haute et basse. Laissez-le vous submerger.

Ahh. C'est tout.

Vous pouvez ignorer ces modifications lors de la préparation de vos modifications, réinitialiser les modifications indésirables et effectuer une validation propre.

Le seul avantage que j'ai vu avec les storyboards par rapport aux XIB d'un point de vue technique est qu'Apple n'a pas encore stérilisé FileMerge pour refuser de fusionner des storyboards en conflit. (FileMerge était capable de fusionner les XIB, mais les versions plus récentes ont cassé cela. Les gars Thxxxx 💜 !!!)

Veuillez déposer de nombreux bogues concernant tous ces problèmes sur http://bugreporter.apple.com/ ! Et n'oubliez pas de créer des entrées sur OpenRadar .

Phil Calvin
la source
6

Jeter ici une autre réponse car cette situation s'est grandement améliorée. Le XML du fichier XIB qui représente le StoryBoard a été considérablement simplifié.

J'ai aussi récemment mordu la balle et commencé à utiliser l'interface de Xcode vers Source Control. Je suis sur la ligne de commande depuis des années et je suis heureux là-bas, mais l'interface est agréable et vous permet de diviser les commits, ce qui est vraiment important si vous utilisez un système de billetterie qui relie les commits.

Quoi qu'il en soit, j'ai remarqué aujourd'hui qu'il y avait un changement sur le storyboard et le diff intégré m'a montré qu'il s'agissait d'un seul attribut dans la balise de document (systemVersion). Donc pas un gros problème.

J'ai lu des articles où les gens disent que les SB ont été interdits dans leurs équipes en raison de problèmes de fusion. Folie totale. Ils sont tellement incroyables, surtout maintenant qu'ils ont une mise en page automatique intelligente intégrée, vous manquez vraiment si vous ne les utilisez pas.

Rob
la source
3

Il est utile de savoir pourquoi cette folie se produit, mais pour ceux qui croient qu'il faut garder leurs projets exempts d'avertissements et qui veulent juste un rapide et sale pour remettre leurs projets à un état sain:

  1. Ne commettez rien avant d'y être explicitement demandé.

  2. Ouvrez Xcode et créez un nouveau storyboard (Commande + N> iOS> Interface utilisateur> Storyboard). Je suppose que vous l'appelez le nom par défaut de Storyboard.storyboard.

  3. Ouvrez le storyboard que Xcode a violé. Je suppose que c'est Base.lproj/Main.storyboard.

  4. Sélectionnez et copiez tout sur le storyboard (Commande + A puis Commande + C).

  5. Ouvrez Storyboard.storyboard.

  6. Copiez et collez tout dans Storyboard.storyboard.

  7. Fermez Xcode.

  8. Ouvrez un terminal et changez de répertoire dans votre référentiel.

  9. Remplacez Main.storyboardpar Storyboard.storyboard( mv Storyboard.storyboard Base.lproj/Main.storyboard).

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

  11. Ne tenez pas compte des modifications apportées à project.pbxprojvia git checkout -- project.pbxproj. Si vous git diffle fichier, vous verrez qu'il vient d'ajouter des informations sur notre storyboard temporaire (qui n'existe plus).

  12. Ouvrez Xcode et voyez que les avertissements ont disparu.

  13. Respirer.

Kayce Basques
la source
0

Travailler sur le même storyboard n'est pas un problème. Mais travailler sur le même viewcontroller qui crée des conflits lors du pull / merge est effrayant. on ne peut pas vraiment éviter que de travailler dans le même viewcontroller pour une grande équipe.

La bonne chose est que la plupart du temps, nous pouvons résoudre les mêmes conflits de contrôleur de vue si nous comprenons la structure xml. Je n'ai jamais manqué de les fusionner en travaillant en équipe. Supposons que vous travaillez avec un viewcontroller. Votre vue est actuellement vide. Veuillez jeter un œil à la structure xml du viewcontroller à partir de l'option de code source.

entrez la description de l'image ici

Le storyboard est xml lié par une balise de type de document. Tout dans le storyboard contient dans la scène sceneID = tag. La balise de scène contient tous les contrôleurs de vue. C'est la base.

Nous avons maintenant ajouté un UILabel et un UIButton sur la vue. Définissez également la disposition automatique des éléments. Maintenant, ça ressemble à:

entrez la description de l'image ici

L'ajout d'un niveau / bouton à viewcontroller a ajouté un nouveau code à l'intérieur de la balise de sous-vue de la vue. Il en ira de même pour l'ajout d'éléments supplémentaires ou toute modification de l'interface utilisateur. Vérifiez attentivement la structure des balises, ce qui est vraiment important pour résoudre les conflits.

Maintenant, nous ajoutons un autre viewcontroller dans le nom du storyboard Homeviewcontroller. L'ajout d'un nouveau contrôleur de vue signifie qu'il ajoute une nouvelle scène sous la balise scènes. Regarde ça:

entrez la description de l'image ici

À ce stade, nous modifierons la structure de manière aléatoire et observerons les problèmes / avertissements. Nous changeons la première balise de fin d'étiquette de viewcontroller et enregistrons le fichier. Maintenant, exécutez-le et regardez l'avertissement. L'erreur dit que la balise de fin n'est pas correcte qui a été créée à partir de la ligne 23. À la ligne 23, nous voyons qu'une contrainte d'étiquette est définie sans balise de fin. C'est le problème. Maintenant, nous mettons la balise de fin et construisons le projet. Après avoir défini la balise de fin, nous pouvons afficher le storyboard avec succès.

entrez la description de l'image ici

En cas d'avertissement de conflit, veuillez comparer avec votre source précédente et la source des modifications. Nous supprimons l'ancien code / redondant, gardons le nouveau code avec la balise start-end appropriée et réparons les choses.

[NB, je mettrai à jour la réponse avec d'autres cas de test lors de la réception]

Jamshed Alam
la source