O Xcode altera o storyboard não modificado e os arquivos XIB

133

Storyboards são uma verdadeira dor de uma perspectiva de fluxo de trabalho git quando várias pessoas estão colaborando neles. Por exemplo, o XML no arquivo .storyboard tem suas <document>tags toolsVersione systemVersionatributos iniciais alterados por qualquer configuração que o manipulador de arquivos mais recente esteja executando. Sincronizar todas as versões do Xcode parece ajudar com precisão toolsVersion, mas systemVersionmuda não importa o que aconteça, dependendo da versão específica do Mac e / ou OS X que o desenvolvedor está executando.

Isso é idiota, mas principalmente inofensivo. O que nos preocupa, porém, é que, em outras ocasiões, algumas outras alterações são feitas automaticamente no storyboard apenas abrindo-as após um git pull. Ou seja, Alice faz alterações em um storyboard, confirma e envia por push para o repositório. Bob então puxa as mudanças de Alice e abre o storyboard para fazer outras mudanças. No momento em que ele abre o storyboard, o ícone do arquivo muda imediatamente para um estado modificado, mas não salvo, e git statusmostra que várias mudanças estranhas ocorreram. Tudo isso sem que Bob tenha alterado nada ou salvo o arquivo por conta própria.

A alteração automatizada mais comum que vemos é o desaparecimento ou reaparecimento de toda a <classes>hierarquia de tags próximo ao final de um arquivo de storyboard. Não descobrimos o que está causando isso. Podemos ter várias versões localizadas de um storyboard em vários diretórios .lproj e, ao abri-los dentro do Interface Builder, a hierarquia de classes pode ser removida espontaneamente de alguns e adicionada a outros, ou deixada sozinha em alguns. Isso causa muito ruído git diff, mas não interrompe nenhuma funcionalidade. Frequentemente adicionaremos seletivamente as mudanças reais que fizemos no índice do git, as confirmaremos e, em seguida, apenas descartamos as alterações espontâneas e sem sentido<classes>alterar. Isso é para manter os commits pequenos e agradáveis, como deveriam ser. Eventualmente, porém, torna-se muito incômodo, já que o Xcode continua refazendo as alterações, e alguém apenas as confirma junto com outras coisas ... o que está bem até que o Xcode de outra pessoa decida alterá-las de volta para não razão aparente. (Nosso histórico de commits tem muitos juramentos sobre isso.)

Alguém mais está vendo esse comportamento? É um bug do Xcode ou um problema de configuração em um ou mais de nossos Macs de desenvolvedor? Vimos algum comportamento semelhante ao colaborar com arquivos XIB, mas os storyboards parecem mais suscetíveis a isso.

JK Laiho
fonte
Na verdade, os projetos Xcode e Git não estão indo muito bem juntos. Não acho que você possa evitar essa bagunça a não ser descartando as alterações desnecessárias - que quase sempre são as alterações de arquivos de projeto para mim e outros arquivos xml que tenho certeza que não alterei. Ficarei feliz se houver algum tipo de 'solução'. Eu gosto do Perforce pela funcionalidade de bloqueio conveniente, não permitindo que o Xcode mude muito, o que provavelmente pode ser feito manualmente para os arquivos que você não vai alterar, mas apenas para revisar.
A-Live
3
Não vale a pena usar storyboards com git ou qualquer outra coisa. Eles não são projetados para serem amigáveis. Desistimos e optamos pelo .xib, que também não é muito bom, mas pelo menos é granular.
ahwulf
Na verdade, descobrimos storyboards bastante interessantes para muitas coisas, embora seja frequentemente necessário misturá-los com XIBs. Se esse bug for corrigido, ficaremos muito felizes em trabalhar com eles na grande maioria das vezes.
JK Laiho
Só tenho que comentar o comentário do ahwulf: o que diabos você quer dizer com eles não são amigos de commit? Eles são arquivos XML / texto, que são os mais amigáveis ​​possível para commits. E eu não tive 'nenhum' problema com o storyboard e um sistema de versionamento, o único problema é claro que o xcode às vezes deleta a tag <classes> e então a readds mais tarde, mas você pode ver isso facilmente se olhar as mudanças com uma GUI git ou git -p ou equivalente para qualquer dvcs. Isso nunca aconteceu com o arquivo .pbxproj como um fyi.
mgrandi
Não consigo entender por que o xcode colocou os blocos de classes dentro do storyboard se ele pode apenas gerar esses blocos lendo os arquivos de classes? eles são uma espécie de "cache"? em caso afirmativo, eles devem ser colocados em um arquivo classes.cache para que possamos excluí-lo do controle de versão ...
hariseldon78

Respostas:

79

Isso não é um bug, é uma consequência de como o Xcode processa arquivos de storyboard. Estou escrevendo um programa diff e merge para arquivos de storyboard (link do GitHub) e passei horas analisando a lógica dos arquivos de storyboard e como o Xcode os processa. Isto é o que descobri:

  • Por que mudanças estranhas ocorrem em arquivos de storyboard? O Xcode usa a API NSXML para analisar arquivos de storyboard em alguma NSSetestrutura de árvore lógica. Quando o Xcode precisa gravar alterações, ele cria um NSXMLDocumentbaseado na estrutura de árvore lógica, limpa o arquivo de storyboard e chama XMLDataWithOptions:para preencher o arquivo novamente. Como os conjuntos não preservam a ordem de seus elementos, mesmo a menor modificação pode alterar todo o arquivo XML do storyboard.

  • Por que a tag de classe desaparece ou reaparece aleatoriamente? A <class>seção nada mais é do que um cache interno do Xcode. O Xcode o usa para armazenar informações sobre as classes. O cache muda frequentemente. Elementos são adicionados quando os .h/.marquivos de classe são abertos e removidos quando o Xcode suspeita que eles estão desatualizados (pelo menos os Xcodes mais antigos se comportam assim). Quando você salva o storyboard, a versão atual do cache é despejada, e é por isso que a <class>seção costuma mudar ou até mesmo desaparecer.

Eu não fiz engenharia reversa do Xcode; Fiz essas observações experimentando arquivos Xcode e storyboard. No entanto, tenho quase 100% de certeza de que funciona assim.

Conclusões :

  • A seção do cache não é importante; você pode ignorar com segurança qualquer alteração nele.
  • Ao contrário do que você pode encontrar em todos os fóruns, mesclar arquivos de storyboards não é uma tarefa complicada. Por exemplo, vamos supor que você alterou o MyController1controlador de visualização em um documento de storyboard. Abra o arquivo de storyboard e encontre algo assim <viewController id=”ory-XY-OBM” sceneMemberID=”MyController1”>. Você pode confirmar com segurança apenas as alterações nesta seção e ignorar todo o resto. Se você alterou segues ou restrições, também comprometa tudo o que estiver “ory-XY-OBM”dentro. Simples!
Marcin Olawski
fonte
9
Alguma atualização na ferramenta xcode diff / merge? Parece que será muito útil para esta comunidade.
Tony
1
Você pode obter o aplicativo da minha página da web (ver perfil). O aplicativo é 100% gratuito.
Marcin Olawski
1
Para mim, dividir storyboards tanto quanto possível == usando XIBs. Se você quiser ter tudo fatiado, é mais fácil e melhor usar XIBs
Marcin Olawski
7
"Eu não fiz a engenharia reversa do Xcode; fiz essas observações experimentando com arquivos Xcode e storyboard." Isso é engenharia reversa (superficial) e é legal . :-)
Constantino Tsarouhas
14
“Isso não é um bug, é uma consequência de como o Xcode processa os arquivos do storyboard.” Respeitosamente, a 2ª metade desta frase não explica nem racionaliza a primeira. Eu corrigiria para: "Este é um bug. É uma consequência [n infelizmente não resolvida e altamente irritante] de como o XCode processa arquivos .xib." Do XCode 5.x até o 6.2 (hoje, 150311) .xib arquivos de forma alguma modificados pelo desenvolvedor, meramente visualizados em IB, sofrem alterações xml gratuitas. Este é um bug bruto que afeta a produtividade. Respostas como "NBD, apenas lidar com pedaços no git" me deixam sem palavras.
semanalmente em
18

Este é um bug no XCode 4.5+, espero que seja corrigido, e sim é um PITA.

Aqui está o bug completo da Apple

Como evitar edições gratuitas do Xcode em arquivos de storyboard?

usuário deletado
fonte
1
Mesma coisa em 4.6. Talvez não seja um bug.
Thromordyn
4.6.3 ainda tem. Não posso dizer que o storyboard / xibs funcionou bem
houbysoft
1
"Não é um bug, é um recurso": -S
MrTJ
Não há evidências de que isso seja um bug - um aborrecimento, sim, mas pode ser apenas como o Xcode faz as coisas
Thomas Watson
1
7.0.1 não trouxe nenhuma mudança para isso.
Andris Zalitis
11

Esse problema pode ser atenuado de alguma forma pelo uso extremamente criterioso de git add -pqualquer um dos arquivos gerados pelo Xcode, incluindo storyboards, XIBs, modelos de dados centrais e arquivos de projeto, todos os quais sofrem modificações transitórias semelhantes que não têm impacto na interface / modelo / projeto.

As mudanças inúteis mais comuns que vi nos storyboards são os números da versão do sistema (como você mencionou) e a constante adição e remoção da <classes>seção, cuja omissão nunca vi causar problemas. Para XIBs, é a adição e remoção de <reference key="NSWindow"/>, o que nem é uma classe no Cocoa Touch. Apenas Uau.

Pense nisso como o mar: há maré alta e maré baixa. Deixe isso passar por você.

Ahh. É isso aí.

Você pode ignorar essas modificações ao preparar suas alterações, redefinir as alterações indesejadas e fazer um commit limpo.

A única vantagem que vi nos storyboards sobre os XIBs de um ponto de vista técnico é que a Apple ainda não castrou o FileMerge para se recusar a mesclar storyboards em conflito. (O FileMerge costumava ser capaz de mesclar XIBs, mas as versões mais recentes quebraram isso. Thxxxx pessoal 💜 !!!)

Registre muitos bugs sobre todos esses problemas em http://bugreporter.apple.com/ ! E não se esqueça de criar entradas no OpenRadar .

Phil Calvin
fonte
6

Colocando em outra resposta aqui, porque esta situação melhorou muito. O XML para o arquivo XIB que representa o StoryBoard foi bastante simplificado.

Recentemente, também mordi a bala e comecei a usar a interface no Xcode to Source Control. Estou na linha de comando há anos e estou feliz por isso, mas a interface é boa e permite dividir commits, o que é muito importante se você usar um sistema de tíquetes com links para commits.

De qualquer forma, notei hoje que houve uma mudança no storyboard e o diff integrado me mostrou que era um único atributo na tag do documento (systemVersion). Portanto, não é grande coisa.

Eu li artigos onde as pessoas dizem que os SBs foram proibidos em suas equipes por causa de problemas de fusão. Loucura total. Eles são tão incríveis, especialmente agora que têm autolayout inteligente integrado, você realmente está perdendo se não os estiver usando.

Roubar
fonte
3

É útil saber por que essa insanidade está acontecendo, mas para aqueles que acreditam em manter seus projetos livres de avisos e que querem apenas um rápido e sujo para que seus projetos voltem a um estado saudável:

  1. Não comprometa nada até que seja explicitamente instruído.

  2. Abra o Xcode e crie um novo storyboard (Command + N> iOS> Interface do usuário> Storyboard). Presumo que você o chame de nome padrão de Storyboard.storyboard.

  3. Abra o storyboard que o Xcode violou. Vou assumir que sim Base.lproj/Main.storyboard.

  4. Selecione e copie tudo no storyboard (Command + A, em seguida, Command + C).

  5. Aberto Storyboard.storyboard.

  6. Copie e cole tudo em Storyboard.storyboard.

  7. Feche o Xcode.

  8. Abra um terminal e mude os diretórios para o seu repositório.

  9. Substitua Main.storyboardpor Storyboard.storyboard( mv Storyboard.storyboard Base.lproj/Main.storyboard).

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

  11. Desconsidere as alterações para project.pbxprojvia git checkout -- project.pbxproj. Se você git diffo arquivo, verá que ele acaba de adicionar informações sobre nosso storyboard temporário (que não existe mais).

  12. Abra o Xcode novamente e veja se os avisos desapareceram.

  13. Respirar.

Kayce Basques
fonte
0

Trabalhar no mesmo storyboard não é um problema. Mas trabalhar no mesmo viewcontroller que cria conflitos no pull / merge é assustador. não podemos evitar que trabalhe no mesmo viewcontroller para uma grande equipe.

O bom é que, na maioria das vezes, podemos consertar os mesmos conflitos do viewcontroller se entendermos a estrutura xml. Nunca deixei de mesclar estes enquanto trabalhava em equipe. Suponha que você esteja trabalhando com um viewcontroller. Sua visão está em branco no momento. Por favor, dê uma olhada na estrutura xml do viewcontroller da opção de código-fonte.

insira a descrição da imagem aqui

Storyboard é xml delimitado pela tag de tipo de documento. Tudo no storyboard contém na cena sceneID = tag. a marca de cena contém todos os controladores de visualização. Isso é o básico.

Agora adicionamos um UILabel e um UIButton na visualização. Defina também o layout automático dos elementos. Agora parece:

insira a descrição da imagem aqui

Adicionar um nível / botão ao viewcontroller adicionou algum código novo dentro da tag subview da view. A mesma coisa acontecerá com a adição de mais elementos ou quaisquer alterações da IU. Verifique cuidadosamente a estrutura da tag, que é realmente importante para corrigir quaisquer conflitos.

Agora adicionamos outro viewcontroller no nome do storyboard Homeviewcontroller. Adicionar um novo controlador de visualização significa que ele adiciona uma nova cena sob a marca de cenas. Veja isso:

insira a descrição da imagem aqui

Neste ponto, vamos mudar a estrutura aleatoriamente e observar os problemas / avisos. Mudamos a etiqueta final do primeiro viewcontroller e salvamos o arquivo. Agora execute-o e veja o aviso. O erro diz que a tag final não está correta, criada a partir da linha 23. Na linha 23, vemos que uma restrição de rótulo está definida sem tag final. Esse é o problema. Agora colocamos a tag final e construímos o projeto. Depois de definir a tag final, podemos visualizar o storyboard com sucesso.

insira a descrição da imagem aqui

Ao enfrentar qualquer aviso de conflito, compare com sua fonte anterior e altere a fonte. Removemos o código antigo / redundante, mantemos o novo código com tag start-end adequada e consertamos as coisas.

[NB, vou atualizar a resposta com mais alguns casos de teste quando chegar o momento]

Jamshed Alam
fonte