Xcode cambia el storyboard no modificado y los archivos XIB

132

Los guiones gráficos son más bien un dolor real desde la perspectiva del flujo de trabajo de git cuando varias personas colaboran en ellos. Por ejemplo, el XML en el archivo .storyboard tiene sus <document>etiquetas toolsVersiony systemVersionatributos iniciales alterados por cualquier configuración que esté ejecutando el manipulador de archivos más reciente. Sincronizar las versiones de Xcode de todo el mundo parece ayudar con precisión toolsVersion, pero systemVersioncambia sin importar qué, dependiendo de la versión específica de Mac y / o OS X que el desarrollador esté ejecutando.

Esto es idiota, pero sobre todo inofensivo. Sin embargo, lo que nos preocupa es que en otros momentos se realizan automáticamente otros cambios en el guión gráfico simplemente abriéndolos después de a git pull. Es decir, Alice realiza cambios en un guión gráfico, los confirma y los empuja al repositorio. Bob luego saca los cambios de Alice y abre el guión gráfico para realizar más cambios. En el momento en que abre el guión gráfico, el icono del archivo cambia inmediatamente a un estado modificado pero no guardado, y git statusmuestra que se han producido varios cambios extraños. Todo esto sin que Bob haya cambiado nada o guardado el archivo él mismo.

El cambio automático más común que estamos viendo es la desaparición o reaparición de toda la <classes>jerarquía de etiquetas cerca del final de un archivo de guión gráfico. No hemos descubierto qué está causando esto. Es posible que tengamos varias versiones localizadas de un guión gráfico en varios directorios .lproj, y al abrirlos dentro de Interface Builder, la jerarquía de clases puede eliminarse espontáneamente de algunos y agregarse a otros, o dejarse solo en algunos. Esto causa mucho ruido git diff, pero en realidad no interrumpe ninguna funcionalidad. A menudo agregaremos selectivamente los cambios reales que realizamos en el índice de git, los confirmaremos y luego simplemente descartaremos lo espontáneo y sin sentido.<classes>cambios Esto es para mantener compromisos pequeños y agradables, como deberían ser. Eventualmente, sin embargo, se vuelve demasiado molesto ya que Xcode sigue volviendo a hacer los cambios, y alguien simplemente los confirma junto con otras cosas ... lo cual está bien hasta que el Xcode de otra persona decida querer volver a cambiarlos sin ningún problema. razón aparente. (Nuestra historia de compromiso tiene muchas palabrotas sobre esto).

¿Alguien más está viendo este comportamiento? ¿Es esto un error de Xcode o un problema de configuración en uno o más de nuestros Mac para desarrolladores? Hemos visto un comportamiento similar al colaborar con archivos XIB, pero los guiones gráficos parecen más susceptibles a esto.

JK Laiho
fuente
De hecho, los proyectos de Xcode y Git no lo están haciendo muy bien juntos. No creo que pueda evitar este desastre de otra manera que descartar los cambios que son innecesarios, que casi siempre son los cambios en los archivos del proyecto para mí y otros archivos xml. Estoy seguro de que no he cambiado. Se alegrará si hay algún tipo de 'solución'. Me gusta Perforce por la funcionalidad de bloqueo conveniente que no permite que Xcode cambie demasiado, eso probablemente se pueda hacer manualmente para los archivos que no va a cambiar sino solo para revisar.
A-Live
3
No vale la pena usar storyboards con git o cualquier otra cosa. No están diseñados para comprometerse amigablemente. Nos rendimos y fuimos con .xib, que tampoco es tan bueno, pero al menos es granular.
ahwulf
En realidad, hemos encontrado guiones gráficos bastante buenos para muchas cosas, aunque a menudo es necesario mezclarlos con XIB. Si alguna vez se soluciona este error, estaremos encantados de trabajar con ellos la gran mayoría de las veces.
JK Laiho
Solo tengo que comentar el comentario de ahwulf: ¿qué quieres decir con que no se comprometen amistosamente? Son archivos XML / de texto, que son lo más amigables que puede obtener. Y no he tenido ningún problema con el guión gráfico y un sistema de versiones, el único problema es, por supuesto, que xcode a veces elimina la etiqueta <classes> y luego la vuelve a leer más tarde, pero puede ver esto fácilmente si observa los cambios con una GUI git o git -p o equivalente para cualquier dvcs. Nunca me ha sucedido esto con el archivo .pbxproj como para tu información.
mgrandi
No puedo entender por qué xcode puso los bloques de clases dentro del guión gráfico si solo puede generar esos bloques leyendo los archivos de clases. ¿son una especie de "caché"? si es así, deben colocarse en un archivo classes.cache para que podamos excluirlo de la versión ...
hariseldon78

Respuestas:

78

Esto no es un error, es una consecuencia de cómo Xcode procesa los archivos del guión gráfico. Estoy escribiendo un programa de diferencias y fusión para archivos de guiones gráficos (enlace GitHub) y he pasado horas analizando la lógica de los archivos de guiones gráficos y cómo Xcode los procesa. Esto es lo que descubrí:

  • ¿Por qué ocurren cambios extraños en los archivos del guión gráfico? Xcode usa la API NSXML para analizar archivos de guiones gráficos en una NSSetestructura de árbol lógico basada en algo . Cuando Xcode necesita escribir cambios, crea una NSXMLDocumentestructura basada en el árbol lógico, borra el archivo del guión gráfico y llama XMLDataWithOptions:para volver a llenar el archivo. Debido a que los conjuntos no conservan el orden de sus elementos, incluso la más mínima modificación podría cambiar todo el archivo XML del guión gráfico.

  • ¿Por qué la etiqueta de clase desaparece o reaparece al azar? La <class>sección no es más que un caché interno de Xcode. Xcode lo usa para almacenar en caché información sobre las clases. El caché cambia a menudo. Los elementos se agregan cuando los .h/.marchivos de clase se abren y se eliminan cuando Xcode sospecha que están desactualizados (al menos los códigos X más antiguos se comportan así). Cuando guarda el guión gráfico, se descarga la versión actual de la memoria caché, por lo que la <class>sección a menudo cambia o incluso desaparece.

No he realizado ingeniería inversa de Xcode; Hice estas observaciones experimentando con Xcode y archivos de guión gráfico. Sin embargo, estoy casi 100% seguro de que funciona de esta manera.

Conclusiones :

  • La sección de caché no es importante; puedes ignorar cualquier cambio en él de forma segura.
  • Al contrario de lo que puede encontrar en todos los foros, fusionar archivos de guiones gráficos no es una tarea complicada. Por ejemplo, supongamos que ha cambiado el MyController1controlador de vista en un documento de guión gráfico. Abra el archivo del guión gráfico y encuentre algo como esto <viewController id=”ory-XY-OBM” sceneMemberID=”MyController1”>. Puede confirmar de forma segura solo los cambios en esta sección e ignorar todo lo demás. Si cambiaste segues o restricciones, también confirma todo lo que tiene “ory-XY-OBM”dentro. ¡Sencillo!
Marcin Olawski
fuente
9
¿Alguna actualización de la herramienta xcode diff / merge? Parece que será súper útil para esta comunidad.
Tony
1
Puede obtener la aplicación desde mi página web (ver perfil). La aplicación es 100% gratis.
Marcin Olawski
1
Para mí, dividir guiones gráficos tanto como sea posible == usando XIB. Si quieres tener todo cortado, es más fácil y mejor usar XIBs
Marcin Olawski
77
"No hice ingeniería inversa con Xcode; hice estas observaciones al experimentar con Xcode y los archivos de storyboard". Eso es ingeniería inversa (superficial), y es genial . :-)
Constantino Tsarouhas
13
"Esto no es un error, es una consecuencia de cómo Xcode procesa los archivos del guión gráfico". Respetuosamente, la segunda mitad de esta oración de ninguna manera explica ni racionaliza la primera. Lo enmendaría a: "Esto es un error. Es una consecuencia [desafortunadamente no resuelta y muy molesta] de cómo XCode procesa los archivos .xib". Desde XCode 5.x hasta 6.2 (hoy, 150311), los archivos .xib de ninguna manera modificados por el desarrollador, simplemente vistos en IB, sufren cambios xml gratuitos. Este es un error grave que afecta la productividad. Respuestas como "NBD, solo trato con trozos en git" me dejan sin palabras.
Cweekly
18

Este es un error en XCode 4.5+, espero que se solucione, y sí, es un PITA.

Aquí está el error completo en Apple

¿Cómo evitar las ediciones gratuitas de Xcode en los archivos del guión gráfico?

Usuario eliminado
fuente
1
Lo mismo en 4.6. Quizás no sea un error.
Thromordyn
4.6.3 todavía lo tiene. Sin embargo, no puedo decir que storyboard / xibs funcionó bien
houbysoft
1
"No es un error, es una característica": -S
MrTJ
No hay evidencia de que esto sea un error, una molestia sí, pero podría ser la forma en que Xcode hace las cosas
Thomas Watson
1
7.0.1 no ha traído ningún cambio a esto.
Andris Zalitis
11

Este problema puede mitigarse un poco mediante el uso extremadamente juicioso de git add -pcualquiera de los archivos generados por Xcode, incluidos los guiones gráficos, los XIB, los modelos de datos básicos y los archivos de proyecto, todos los cuales sufren modificaciones transitorias similares que no tienen impacto en la interfaz / modelo real / proyecto.

Los cambios basura más comunes que he visto en los guiones gráficos son los números de versión del sistema (como usted menciona) y la constante adición y eliminación de la <classes>sección, cuya omisión que nunca he visto causa problemas. Para XIB, es la adición y eliminación de <reference key="NSWindow"/>, que ni siquiera es una clase en Cocoa Touch. Simplemente guau.

Piense en ello como el mar: hay marea alta y baja. Deja que te lave.

Ahh Eso es.

Puede ignorar estas modificaciones al organizar sus cambios, restablecer los cambios no deseados y realizar una confirmación limpia.

La única ventaja que he visto con los guiones gráficos sobre XIB desde un punto de vista técnico es que Apple aún no ha neutralizado FileMerge para negarse a fusionar guiones gráficos en conflicto. (FileMerge solía ser capaz de fusionar XIB, pero las versiones más nuevas lo rompieron. ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡

¡Presente muchos errores sobre todos estos problemas en http://bugreporter.apple.com/ ! Y no olvides crear entradas en OpenRadar .

Phil Calvin
fuente
6

Lanzando otra respuesta aquí porque esta situación ha mejorado mucho. El XML para el archivo XIB que representa el StoryBoard se ha simplificado enormemente.

También he mordido la bala recientemente y comencé a usar la interfaz en Xcode to Source Control. He estado en la línea de comandos durante años y estoy feliz allí, pero la interfaz es agradable y te permite dividir los commits, lo cual es realmente importante si utilizas un sistema de tickets que se vincula a los commits.

De todos modos, me di cuenta hoy de que había un cambio en el guión gráfico y la diferencia incorporada me mostró que era un atributo único en la etiqueta del documento (systemVersion). Así que no es gran cosa.

He leído artículos donde la gente dice que los SB fueron prohibidos en sus equipos debido a problemas de fusión. Locura total. Son tan asombrosos, especialmente ahora que tienen una distribución automática inteligente incorporada, realmente te estás perdiendo si no los estás usando.

Robar
fuente
3

Es útil saber por qué está ocurriendo esta locura, pero para aquellos que creen en mantener sus proyectos libres de advertencias y que solo quieren un proceso rápido y sucio para que sus proyectos vuelvan a un estado saludable:

  1. No cometas nada hasta que se te indique explícitamente.

  2. Abra Xcode y cree un nuevo guión gráfico (Comando + N> iOS> Interfaz de usuario> Guión gráfico). Asumiré que lo llamas el nombre predeterminado de Storyboard.storyboard.

  3. Abra el guión gráfico que Xcode ha violado. Asumiré que esto es Base.lproj/Main.storyboard.

  4. Seleccione y copie todo en el guión gráfico (Comando + A y luego Comando + C).

  5. Abierto Storyboard.storyboard.

  6. Copia y pega todo en Storyboard.storyboard.

  7. Cierra Xcode.

  8. Abra una terminal y cambie los directorios a su repositorio.

  9. Reemplace Main.storyboardcon Storyboard.storyboard( mv Storyboard.storyboard Base.lproj/Main.storyboard).

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

  11. Haga caso omiso de los cambios a project.pbxprojvia git checkout -- project.pbxproj. Si tiene git diffel archivo, verá que acaba de agregar información sobre nuestro guión gráfico temporal (que ya no existe).

  12. Abra Xcode de nuevo y vea que las advertencias han desaparecido.

  13. Respirar.

Kayce vascos
fuente
0

Trabajar en el mismo guión gráfico no es un problema. Pero trabajar en el mismo controlador de vista que crea conflictos en pull / merge es aterrador. Realmente no podemos evitar que funcione en el mismo controlador de vista para un equipo grande.

Lo bueno es que la mayoría de las veces podemos solucionar los mismos conflictos de viewcontroller si entendemos la estructura xml. Nunca fallé en combinarlos mientras trabajaba en equipo. Supongamos que está trabajando con un controlador de vista. Su vista está en blanco actualmente. Por favor, eche un vistazo a la estructura xml de viewcontroller desde la opción de código fuente.

ingrese la descripción de la imagen aquí

Storyboard está limitado por la etiqueta de tipo de documento. Todo en el guión gráfico contiene en la escena sceneID = tag. La etiqueta de escena contiene todos los controladores de vista. Eso es lo básico.

Ahora agregamos un UILabel y un UIButton en la vista. Establezca también la distribución automática de los elementos. Ahora se ve así:

ingrese la descripción de la imagen aquí

Agregar un nivel / botón al controlador de vista agregó un código nuevo dentro de la etiqueta de subvista de la vista. Lo mismo se aplicará para agregar elementos adicionales o cualquier cambio en la interfaz de usuario. Verifique cuidadosamente la estructura de la etiqueta, que es realmente importante para solucionar cualquier conflicto.

Ahora agregamos otro viewcontroller en el nombre del guión gráfico Homeviewcontroller. Agregar un nuevo controlador de vista significa que agrega una nueva escena debajo de la etiqueta de escenas. Mira este:

ingrese la descripción de la imagen aquí

En este punto, cambiaremos la estructura al azar y observaremos los problemas / advertencias. Cambiamos la etiqueta final de la etiqueta viewcontroller y guardamos el archivo. Ahora ejecútelo y mire la advertencia. El error dice que la etiqueta final no es correcta, que se creó a partir de la línea 23. En la línea 23, vemos que se establecen restricciones de etiqueta sin etiqueta final. Ese es el problema. Ahora ponemos la etiqueta final y compilamos el proyecto. Después de configurar la etiqueta final, podemos ver el guión gráfico con éxito.

ingrese la descripción de la imagen aquí

Cuando enfrente cualquier advertencia de conflictos, compare con su fuente anterior y la fuente de cambios. Eliminamos el código antiguo / redundante, conservamos el código nuevo con la etiqueta adecuada de inicio a fin y arreglamos las cosas.

[Nota: actualizaré la respuesta con algunos casos de prueba más cuando llegue el momento]

Jamshed Alam
fuente