[ios] Xcode는 수정되지 않은 스토리 보드 및 XIB 파일을 변경합니다

스토리 보드는 여러 사람이 공동 작업 할 때 git 워크 플로 관점에서 볼 때 가장 큰 고통입니다. 예를 들어, .storyboard 파일의 XML 에는 가장 최근의 파일 조작자가 실행중인 구성에 따라 시작 <document>태그 toolsVersionsystemVersion속성이 변경됩니다. 동기화 모두의 엑스 코드 버전은 정확하게 도움 보인다 toolsVersion,하지만 systemVersion개발자가 실행중인 특정 Mac 및 / 또는 OS X 버전에 따라 무엇을, 아무리을 변경합니다.

이것은 바보이지만 대부분 무해합니다. 그러나 걱정스러운 점은 다른 경우에는 git pull. 다음에 스토리 보드를 열어서 스토리 보드를 자동으로 변경하는 것 입니다. 즉, Alice는 스토리 보드를 변경하고이를 커밋하여 리포지토리에 푸시합니다. Bob은 Alice의 변경 사항을 가져와 스토리 보드를 열어 추가 변경을 수행합니다. 스토리 보드를 여는 순간, 파일 아이콘은 즉시 수정되었지만 저장되지 않은 상태로 변경되며, git status이상한 변화가 많이 발생했음을 나타냅니다. Bob이 아무것도 변경하지 않았거나 파일을 직접 저장하지 않고이 모든 것을 수행했습니다.

우리가보고있는 가장 일반적인 자동 변경 <classes>은 스토리 보드 파일의 끝 부분에서 태그 계층 전체가 사라지거나 다시 나타나는 것입니다 . 우리는 이것을 일으키는 원인을 알지 못했습니다. 여러 .lproj 디렉토리에 여러 현지화 된 스토리 보드 버전이있을 수 있으며 Interface Builder에서이를 열 때 클래스 계층 구조가 일부에서 제거되어 다른 계층에 추가되거나 단독으로 남겨질 수 있습니다. 이로 인해 많은 소음이 발생 git diff하지만 실제로는 기능이 손상되지 않습니다. 우리는 종종 git의 인덱스에 실제로 변경 한 내용을 선택적으로 추가하고, 커밋 한 다음 자연스럽고 무의미한 것을 버립니다.<classes>변화. 이것은 커밋을 작고 멋지게 유지하는 것입니다. Xcode가 변경 사항을 계속 다시 수행하기 때문에 결국 귀찮게하기가 너무 어려워지고 누군가 다른 것들과 함께 분노를 범하게됩니다 … 다른 사람의 Xcode가 변경하지 않기로 결정할 때까지는 괜찮습니다. 명백한 이유. (우리의 커밋 역사는 이것을 맹세합니다.)

다른 사람이이 행동을보고 있습니까? 하나 이상의 개발자 Mac에서 Xcode 버그 또는 구성 문제입니까? 우리는 XIB 파일과 공동 작업 할 때 비슷한 동작을 보았지만 스토리 보드는 이에 더 취약 해 보입니다.



답변

이것은 버그가 아니며, Xcode가 스토리 보드 파일을 처리하는 방식의 결과입니다. 스토리 보드 파일 (GitHub 링크)에 대한 diff and merge 프로그램을 작성 중이며 스토리 보드 파일 논리 및 Xcode가 처리하는 방법을 분석하는 데 몇 시간을 보냈습니다. 이것이 내가 발견 한 것입니다.

  • 스토리 보드 파일에서 왜 이상한 변화가 발생합니까?
    Xcode는 NSXML API를 사용하여 스토리 보드 파일을 일부 NSSet논리 트리 구조 로 구문 분석합니다 . Xcode는 변경 사항을 작성해야 할 때 NSXMLDocument논리 트리 구조를 기반으로 작성 하고 스토리 보드 파일을 지우고 XMLDataWithOptions:파일을 다시 채우기 위해 호출 합니다. 세트는 요소의 순서를 유지하지 않으므로 약간만 수정해도 전체 스토리 보드 XML 파일이 변경 될 수 있습니다.

  • 클래스 태그가 사라지거나 무작위로 다시 나타나는 이유는 무엇입니까?
    <class>섹션은 내부 Xcode 캐시에 지나지 않습니다. Xcode는이를 사용하여 클래스에 대한 정보를 캐시합니다. 캐시는 자주 변경됩니다. .h/.mXcode에서 클래스 파일이 오래되었다고 의심 되면 클래스 파일을 열거 나 제거 할 때 요소가 추가됩니다 (적어도 오래된 Xcode는 이와 같이 동작 함). 스토리 보드를 저장하면 현재 버전의 캐시가 덤프되므로 <class>섹션이 자주 변경되거나 사라집니다.

Xcode를 리버스 엔지니어링하지 않았습니다. Xcode 및 스토리 보드 파일을 실험하여 이러한 관찰을 수행했습니다. 그럼에도 불구하고, 나는 거의 100 %가 이런 식으로 작동한다고 확신합니다.

결론 :

  • 캐시 섹션은 중요하지 않습니다. 변경 사항을 무시해도됩니다.
  • 모든 포럼에서 찾을 수있는 것과는 달리 스토리 보드 파일을 병합하는 것은 복잡한 작업이 아닙니다. 예를 들어 MyController1스토리 보드 문서에서 뷰 컨트롤러 를 변경했다고 가정 해 봅시다 . 스토리 보드 파일을 열고 이와 같은 것을 찾으십시오
    <viewController id=”ory-XY-OBM” sceneMemberID=”MyController1”>. 이 섹션의 변경 사항 만 안전하게 커밋하고 다른 모든 항목은 무시할 수 있습니다. segues 또는 constraints를 변경 한 경우 “ory-XY-OBM”내부에있는 내용 도 커밋하십시오 . 단순한!

답변

이것은 XCode 4.5 +의 버그이며 수정되기를 바랍니다.

Apple의 전체 버그는 다음과 같습니다.

스토리 보드 파일에 대한 Xcode의 무의미한 편집을 피하는 방법은 무엇입니까?


답변

이 문제는 매우 신중하게 사용함으로써 다소 완화 될 수 있습니다. git add -p 스토리 보드, XIB, 코어 데이터 모델 및 프로젝트 파일을 포함하여 Xcode에서 생성 된 모든 파일 모두는 실제 인터페이스 / 모델 / 계획.

스토리 보드에서 본 가장 일반적인 정크 변경 사항은 시스템 버전 번호 (설명한대로)와 <classes>섹션 의 지속적인 추가 및 제거입니다 . XIB의 경우 <reference key="NSWindow"/>Cocoa Touch의 클래스가 아닌을 추가 및 제거 합니다. 와우

바다처럼 생각하십시오. 만조와 간조가 있습니다. 당신을 씻어 보자.

아 그게 다야.

변경 사항을 스테이징 할 때 이러한 수정 사항을 무시하고 정크 변경 사항을 재설정하고 깔끔하게 커밋 할 수 있습니다.

기술적 인 관점에서 XIB에 비해 스토리 보드에서 내가 본 단일 이점은 Apple이 충돌하는 스토리 보드 병합을 거부하기 위해 FileMerge를 아직 중립화하지 않았다는 것입니다. (FileMerge는 XIB를 병합 할 수 있었지만 최신 버전에서는 문제가 발생했습니다. Thxxxx guys ? !!!)

http://bugreporter.apple.com/ 에서 이러한 모든 문제에 대한 버그를 많이 제출하십시오 ! OpenRadar에서 항목을 작성하는 것을 잊지 마십시오 .


답변

이 상황이 크게 개선되었으므로 여기에 다른 대답을 던졌습니다. StoryBoard를 나타내는 XIB 파일의 XML이 크게 단순화되었습니다.

또한 최근에 글 머리 기호를 물었고 Xcode의 인터페이스를 소스 제어에 사용하기 시작했습니다. 나는 수년간 커맨드 라인에 있었고 행복했지만 인터페이스는 훌륭하고 커밋을 분할 할 수 있습니다. 커밋에 연결되는 티켓팅 시스템을 사용하는 경우 정말 중요합니다.

어쨌든, 오늘 스토리 보드에 변경 사항이 있으며 내장 diff가 문서 태그 (systemVersion)의 단일 속성이라는 것을 알았습니다. 큰 문제는 아닙니다.

나는 사람들이 합병 문제로 인해 SB가 팀에서 불법화되었다고 말하는 기사를 읽었습니다. 총 광기. 그들은 특히 놀랍습니다. 특히 지능형 자동 레이아웃이 내장되어 있으므로 사용하지 않으면 실제로 빠져 있습니다.


답변

이런 광기가 발생 했는지 아는 것이 도움 이되지만, 프로젝트를 경고없이 유지하고 프로젝트를 건강 상태로 되돌릴 수있는 빠르고 더러운 것을 원하는 사람들에게는 다음과 같습니다.

  1. 명시 적으로 지시 할 때까지 아무것도하지 마십시오.

  2. Xcode를 열고 새 스토리 보드를 만듭니다 (Command + N> iOS> 사용자 인터페이스> 스토리 보드). 기본 이름 인이라고 가정합니다 Storyboard.storyboard.

  3. Xcode가 위반 한 스토리 보드를 엽니 다. 이것이라고 가정합니다 Base.lproj/Main.storyboard.

  4. 스토리 보드의 모든 것을 선택하여 복사하십시오 (Command + A, Command + C).

  5. 를 엽니 다 Storyboard.storyboard.

  6. 에 모든 내용을 복사하여 붙여 넣습니다 Storyboard.storyboard.

  7. Xcode를 닫습니다.

  8. 터미널을 열고 디렉토리를 저장소로 변경하십시오.

  9. 교체 Main.storyboard와 함께 Storyboard.storyboard( mv Storyboard.storyboard Base.lproj/Main.storyboard).

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

  11. project.pbxproj통한 변경 사항은 무시하십시오 git checkout -- project.pbxproj. git diff파일 인 경우 임시 스토리 보드 (더 이상 존재하지 않음)에 대한 정보를 추가 한 것입니다.

  12. Xcode 백업을 열고 경고가 사라 졌는지 확인하십시오.

  13. 숨 쉬세요.


답변

동일한 스토리 보드에서 작업하는 것은 문제가되지 않습니다. 그러나 끌어 오기 / 병합시 충돌을 일으키는 동일한 뷰 컨트롤러에서 작업하는 것은 무섭습니다. 우리는 큰 팀을 위해 동일한 뷰 컨트롤러에서 작업하는 것을 피할 수 없습니다.

XML 구조를 이해하면 대부분 동일한 뷰 컨트롤러 충돌을 해결할 수 있습니다. 팀에서 일하는 동안 나는 이것을 병합하지 못했습니다. 뷰 컨트롤러로 작업한다고 가정 해보십시오. 보기가 현재 비어 있습니다. 소스 코드 옵션에서 viewcontroller의 xml 구조를 살펴보십시오.

여기에 이미지 설명을 입력하십시오

스토리 보드는 문서 유형 태그로 묶인 xml입니다. 스토리 보드의 모든 내용은 scene sceneID = 태그에 포함됩니다. 장면 태그는 모든 뷰 컨트롤러를 보유합니다. 그게 기본입니다.

이제 뷰에 UILabel과 UIButton을 추가했습니다. 요소의 자동 레이아웃도 설정하십시오. 이제 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

viewcontroller에 레벨 / 버튼을 추가하면 뷰의 subview 태그 안에 새로운 코드가 추가되었습니다. 요소를 추가하거나 UI를 변경해도 마찬가지입니다. 충돌을 해결하는 데 정말로 중요한 태그 구조를 신중하게 확인하십시오.

이제 스토리 보드 이름 Homeviewcontroller에 다른 viewcontroller를 추가합니다. 새로운 뷰 컨트롤러를 추가한다는 것은 scenes 태그 아래에 새로운 장면을 추가한다는 것을 의미합니다. 이거 봐요:

여기에 이미지 설명을 입력하십시오

이 시점에서 우리는 구조를 무작위로 바꾸고 이슈 / 경고를 관찰 할 것입니다. 첫 번째 viewcontroller 레이블 끝 태그를 변경하고 파일을 저장합니다. 이제 실행하고 경고를보십시오. 23 행에서 작성된 종료 태그가 올바르지 않다는 오류가 표시됩니다. 23 행에서 레이블 제한이 종료 태그없이 설정되어 있습니다. 그게 문제입니다. 이제 종료 태그를 넣고 프로젝트를 빌드하십시오. 종료 태그를 설정하면 스토리 보드를 성공적으로 볼 수 있습니다.

여기에 이미지 설명을 입력하십시오

충돌에 대한 경고가 발생하면 이전 소스와 변경 소스를 비교하십시오. 이전 / 이중 코드를 제거하고 새 코드를 적절한 태그 시작으로 유지하고 문제를 해결합니다.

[NB, 시간이 걸리면 더 많은 테스트 사례로 답변을 업데이트합니다.]


답변