ios Xcode 更改未修改的故事板和 XIB 文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13233181/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Xcode changes unmodified storyboard and XIB files
提问by JK Laiho
Storyboards are rather a royal pain from a git workflow perspective when multiple people are collaborating on them. For example, the XML in the .storyboard file has its starting <document>
tag's toolsVersion
and systemVersion
attributes altered by whatever configuration the most recent file manipulator happens to be running. Synchronizing everybody's Xcode versions precisely seems to help with toolsVersion
, but systemVersion
changes no matter what, depending on the specific Mac and/or OS X version the developer is running.
从 git 工作流程的角度来看,当多人协作时,故事板是相当痛苦的。例如,.storyboard 文件中的 XML 的起始<document>
标记toolsVersion
和systemVersion
属性会被最新的文件操纵器碰巧运行的任何配置更改。精确地同步每个人的 Xcode 版本似乎有助于toolsVersion
,但systemVersion
无论如何都会发生变化,具体取决于开发人员运行的特定 Mac 和/或 OS X 版本。
This is idiotic, but mostly harmless. What worries us, though, is that at other times some other changes are automatically made to the storyboard just by opening them after a git pull
. That is to say, Alice makes changes to a storyboard, commits and pushes them to the repository. Bob then pulls Alice's changes and opens up the storyboard to make further changes. The moment he opens the storyboard, the file icon immediately changes to a modified-but-unsaved state, and a git status
shows that any number of weird changes have occurred. All this without Bob having changed anything or saved the file himself.
这是愚蠢的,但大多是无害的。然而,让我们担心的是,在其他时候,只需在git pull
. 也就是说,Alice 对故事板进行更改,提交并将它们推送到存储库。Bob 然后拉出 Alice 的更改并打开故事板以进行进一步的更改。他打开故事板的那一刻,文件图标立即更改为已修改但未保存的状态,并且git status
显示发生了任意数量的奇怪更改。所有这一切都没有鲍勃更改任何内容或自己保存文件。
The most common automated change we're seeing is the disappearance or reappearance of the entire <classes>
tag hierachy near the end of a storyboard file. We haven't figured out what is causing this. We may have several localized versions of a storyboard in various .lproj directories, and when opening them inside Interface Builder, the class hierarchy may spontaneously be removed from some and added into others, or left alone in some. This causes a lot of noise in git diff
, but it doesn't actually break any functionality. We will often selectively add the actual changes we made into git's index, commit those, and then just discard the spontaneous, nonsensical <classes>
changes. This is to keep commits small and nice, as they should be. Eventually, though, it just becomes too much to bother with since Xcode keeps re-doing the changes, and someone just ragecommits them along with some other stuff... which is fine until someone else's Xcode decides to want to change them back for no apparent reason. (Our commit history has a lot of swearing over this.)
我们看到的最常见的自动更改是<classes>
故事板文件末尾附近的整个标签层次结构的消失或重新出现。我们还没有弄清楚是什么导致了这种情况。我们可能在不同的 .lproj 目录中有多个本地化版本的故事板,当在 Interface Builder 中打开它们时,类层次结构可能会自发地从某些目录中删除并添加到其他目录中,或者在某些目录中单独存在。这会在 中引起很多噪音git diff
,但实际上并没有破坏任何功能。我们经常会选择性地将我们所做的实际更改添加到 git 的索引中,提交这些,然后丢弃自发的、无意义的<classes>
变化。这是为了保持提交小而漂亮,因为它们应该是。但是,最终,由于 Xcode 不断地重新进行更改,所以它变得太麻烦了,并且有人只是将它们与其他一些东西一起提交......这很好,直到其他人的 Xcode 决定想要将它们更改回来明显的原因。(我们的提交历史对此有很多发誓。)
Is anyone else seeing this behaviour? Is this an Xcode bug or a configuration issue on one or more of our developer Macs? We've seen some similar behaviour when collaborating with XIB files, but storyboards seem more susceptible to this.
还有其他人看到这种行为吗?这是 Xcode 错误还是我们的一台或多台开发人员 Mac 上的配置问题?我们在与 XIB 文件协作时看到了一些类似的行为,但故事板似乎更容易受到这种影响。
采纳答案by Marcin Olawski
This is not a bug, this is a consequence of how Xcode processes storyboard files. I am writing a diff and merge program for storyboard files (GitHub link)and I have spent hours analyzing the storyboard files logic and how Xcode processes it. This is what I discovered:
这不是错误,这是 Xcode 如何处理故事板文件的结果。我正在为情节提要文件(GitHub 链接)编写一个差异和合并程序,我花了数小时分析情节提要文件逻辑以及 Xcode 如何处理它。这是我发现的:
Why do weird changes occur in storyboard files?Xcode uses the NSXML API to parse storyboard files into some
NSSet
-based logical tree structure. When Xcode needs to write changes it creates anNSXMLDocument
based on the logical tree structure, clears the storyboard file and callsXMLDataWithOptions:
to fill the file again. Because sets do not preserve the order of their elements, even the slightest modification could change the whole storyboard XML file.Why does the class tag disappear or reappear randomly?The
<class>
section is nothing more than an internal Xcode cache. Xcode use it to cache information about classes. The cache changes often. Elements are added when class.h/.m
files are opened and removed when Xcode suspects they are outdated (at least older Xcodes behave like this). When you save the storyboard, the currentversion of the cache is dumped, which is why the<class>
section often changes or even disappears.
为什么故事板文件会发生奇怪的变化?Xcode 使用 NSXML API 将故事板文件解析为一些
NSSet
基于逻辑的树结构。当 Xcode 需要写入更改时,它会NSXMLDocument
根据逻辑树结构创建一个,清除故事板文件并XMLDataWithOptions:
再次调用填充文件。因为集合不保留其元素的顺序,所以即使是最轻微的修改也可能改变整个故事板 XML 文件。为什么类标签会随机消失或重新出现?该
<class>
部分只不过是一个内部 Xcode 缓存。Xcode 使用它来缓存有关类的信息。缓存经常变化。.h/.m
当 Xcode 怀疑它们已过时(至少较旧的 Xcode 表现得像这样)时,会在打开类文件时添加元素并删除它们。当您保存故事板时,缓存的当前版本将被转储,这就是该<class>
部分经常更改甚至消失的原因。
I have not reverse-engineered Xcode; I made these observations by experimenting with Xcode and storyboard files. Nevertheless, I am almost 100% sure it works this way.
我没有对 Xcode 进行逆向工程;我通过尝试使用 Xcode 和故事板文件进行了这些观察。尽管如此,我几乎 100% 确定它是这样工作的。
Conclusions:
结论:
- Cache section is unimportant; you can safely ignore any change in it.
- Contrary to what you can find on all forums, merging storyboards files is not a complicated task. For example, let's assume you changed
MyController1
view controller in a storyboard document. Open the storyboard file, and find something like this<viewController id=”ory-XY-OBM” sceneMemberID=”MyController1”>
. You can safely commit only changes in this section and ignore everything else. If you changed segues or constraints, also commit anything that has“ory-XY-OBM”
inside. Simple!
- 缓存部分不重要;您可以放心地忽略其中的任何更改。
- 与您在所有论坛上可以找到的相反,合并故事板文件并不是一项复杂的任务。例如,假设您更改
MyController1
了故事板文档中的视图控制器。打开故事板文件,找到类似这样的内容<viewController id=”ory-XY-OBM” sceneMemberID=”MyController1”>
。您可以安全地仅提交此部分中的更改而忽略其他所有内容。如果您更改了 segue 或约束,请同时提交“ory-XY-OBM”
内部的任何内容。简单的!
回答by deleted_user
This is a bug in XCode 4.5+, I hope it gets fixed, and yes its a PITA.
这是 XCode 4.5+ 中的一个错误,我希望它得到修复,是的,它是一个 PITA。
Here's the full bug at Apple
这是 Apple 的完整错误
回答by Phil Calvin
This issue can be mitigated somewhat by extremely judicious use of git add -p
on any of Xcode's generated files, including storyboards, XIBs, Core Data models, and project files, all of which suffer from similar transient modifications that have no impact on the actual interface/model/project.
通过非常明智地使用git add -p
Xcode 生成的任何文件,包括情节提要、XIB、核心数据模型和项目文件,可以在一定程度上缓解此问题,所有这些都遭受类似的瞬态修改,对实际界面/模型没有影响/项目。
The most common junk changes I've seen on storyboards are the system version numbers (as you mention) and the constant addition and removal of the <classes>
section, the omission of which I have never seen cause problems. For XIBs, it's the addition and removal of <reference key="NSWindow"/>
, which isn't even a class in Cocoa Touch. Just wow.
我在故事板上看到的最常见的垃圾更改是系统版本号(如您所述)以及该部分的不断添加和删除<classes>
,我从未见过遗漏会导致问题。对于 XIB 来说,就是添加和删除<reference key="NSWindow"/>
,这甚至不是 Cocoa Touch 中的一个类。哇哦。
Think of it like the sea: there is both a high and low tide. Let it wash over you.
把它想象成大海:有涨潮也有退潮。让它冲刷你。
Ahh. That's it.
啊。就是这样。
You can ignore these modifications when staging your changes, reset the junk changes, and make a clean commit.
您可以在暂存更改时忽略这些修改,重置垃圾更改并进行干净提交。
The single advantage I've seen with storyboards over XIBs from a technical standpoint is that Apple has not yet neutered FileMerge to refuse to merge conflicted storyboards. (FileMerge used to be able to merge XIBs, but newer versions broke that. Thxxxx guys !!!)
从技术角度来看,我所看到的故事板优于 XIB 的唯一优势是,Apple 尚未中止 FileMerge 以拒绝合并有冲突的故事板。(FileMerge 曾经能够合并 XIB,但新版本打破了这一点。Thxxxx 伙计们!!!)
Please file lots of bugs about all of these problems at http://bugreporter.apple.com/! And don't forget to create entries on OpenRadar.
请在http://bugreporter.apple.com/ 上提交有关所有这些问题的大量错误!并且不要忘记在OpenRadar上创建条目。
回答by Rob
Throwing on another answer here because this situation has improved greatly. The XML for the XIB file that represents the StoryBoard has been greatly simplified.
在这里抛出另一个答案,因为这种情况已大大改善。表示 StoryBoard 的 XIB 文件的 XML 已大大简化。
I have also recently bitten the bullet and started to use the interface in Xcode to Source Control. I have been on the command line for years and happy there, but the interface is nice and it lets you split commits, which is really important if you use a ticketing system that links to commits.
我最近也硬着头皮开始使用 Xcode 中的接口来进行源代码控制。我已经在命令行上工作多年并且在那里很高兴,但是界面很好,它可以让您拆分提交,如果您使用链接到提交的票务系统,这非常重要。
Anyway, I noticed today that there was a change on the storyboard and the built in diff showed me it was a single attribute in the document tag (systemVersion). So not a big deal.
无论如何,我今天注意到故事板上有一个变化,内置的差异显示它是文档标签(systemVersion)中的一个属性。所以没什么大不了的。
I have read articles where people say SBs were outlawed on their teams because of merging issues. Total madness. They are so amazing, especially now that they have intelligent autolayout built in, you are really missing out if you are not using them.
我读过一些文章,有人说由于合并问题,SB 在他们的团队中被取缔。彻底的疯狂。它们是如此惊人,尤其是现在它们内置了智能自动布局,如果您不使用它们,您真的会错过。
回答by Kayce Basques
It's helpful to know whythis insanity is happening, but for those who believe in keeping their projects free of warnings and who just want a quick-and-dirty to get their projects back to a healthy state:
知道为什么会发生这种疯狂是有帮助的,但对于那些相信让他们的项目没有警告并且只想快速和肮脏地让他们的项目恢复健康状态的人来说:
Don't commit anything until explicitly instructed.
Open Xcode and create a new storyboard (Command+N > iOS > User Interface > Storyboard). I'll assume you call it the default name of
Storyboard.storyboard
.Open the storyboard that Xcode has violated. I'll assume this is
Base.lproj/Main.storyboard
.Select and copy everything on the storyboard (Command+A then Command+C).
Open
Storyboard.storyboard
.Copy and paste everything into
Storyboard.storyboard
.Close Xcode.
Open a terminal and change directories to your repository.
Replace
Main.storyboard
withStoryboard.storyboard
(mv Storyboard.storyboard Base.lproj/Main.storyboard
).git add Base.lproj/Main.storyboard; git commit -m "Fix Xcode's insanity."
Disregard the changes to
project.pbxproj
viagit checkout -- project.pbxproj
. If yougit diff
the file, you'll see that it has just added information about our temporary storyboard (which no longer exists).Open Xcode back up and see that the warnings has disappeared.
Breathe.
在明确指示之前不要提交任何内容。
打开 Xcode 并创建一个新的故事板(Command+N > iOS > 用户界面 > 故事板)。我假设您将其称为
Storyboard.storyboard
.打开 Xcode 违反的故事板。我会假设这是
Base.lproj/Main.storyboard
.选择并复制故事板上的所有内容(Command+A 然后是 Command+C)。
打开
Storyboard.storyboard
。将所有内容复制并粘贴到
Storyboard.storyboard
.关闭 Xcode。
打开终端并将目录更改为您的存储库。
替换
Main.storyboard
为Storyboard.storyboard
(mv Storyboard.storyboard Base.lproj/Main.storyboard
)。git add Base.lproj/Main.storyboard; git commit -m "Fix Xcode's insanity."
忽略对
project.pbxproj
via的更改git checkout -- project.pbxproj
。如果您查看git diff
该文件,您会看到它刚刚添加了有关我们的临时故事板(不再存在)的信息。打开 Xcode 备份,看到警告已经消失。
呼吸。
回答by Jamshed Alam
Working on same storyboard is not a problem. But working on same viewcontroller which creates conflicts on pull/merge is frightening. we can not really avoid that working in same viewcontroller for a large team.
在同一个故事板上工作不是问题。但是在拉/合并时产生冲突的同一个视图控制器上工作是可怕的。对于一个大团队,我们无法真正避免在同一个视图控制器中工作。
Good thing is, most of the time we can fixed the same viewcontroller conflicts if we understand the xml structure. I never failed to merge these while working in team. Suppose you are working with a viewcontroller. Your view is blank currently. Please ,have a look at the viewcontroller's xml structure from source code option.
好消息是,如果我们了解 xml 结构,大多数时候我们可以修复相同的视图控制器冲突。我在团队合作时从来没有失败过合并这些。假设您正在使用视图控制器。您的视图目前是空白的。请从源代码选项中查看视图控制器的 xml 结构。
Storyboard is xml bounded by document type tag. Everything in the storyboard contains in scene sceneID= tag. scene tag holds every viewcontrollers. Thats the basic.
故事板是由文档类型标签限制的 xml。故事板中的所有内容都包含在场景 sceneID= 标签中。场景标签包含每个视图控制器。这就是基本的。
Now we added a UILabel and a UIButton on the view. Also set the autolayout of the elements. Now it's looks like :
现在我们在视图上添加了一个 UILabel 和一个 UIButton。还要设置元素的自动布局。现在它看起来像:
Adding a level/button to viewcontroller added some new code inside the subview tag of the view. Same thing will go for further element addition or any UI changes. Carefully check the tag structure which is really important to fix any conflicts.
向视图控制器添加级别/按钮在视图的子视图标记中添加了一些新代码。同样的事情将用于进一步的元素添加或任何 UI 更改。仔细检查标记结构,这对于修复任何冲突非常重要。
Now we add another viewcontroller in the storyboard name Homeviewcontroller. Adding a new viewcontroller means it adds a new scene under scenes tag. Look at this:
现在我们在故事板名称 Homeviewcontroller 中添加另一个视图控制器。添加一个新的视图控制器意味着它会在场景标签下添加一个新场景。看这个:
At this point, we will change the structure randomly and observe the issues/warnings. We change first viewcontroller label end tag and save the file. Now run it and look at the warning. Error says end tag is not correct which created from line 23. In line 23 , we see a label constrains is set with no end tag. That's the problem. Now we put the end tag and build the project. After setting end tag, we can view the storyboard successfully.
此时,我们将随机更改结构并观察问题/警告。我们更改第一个视图控制器标签结束标记并保存文件。现在运行它并查看警告。错误表示从第 23 行创建的结束标记不正确。在第 23 行中,我们看到标签约束设置为没有结束标记。那就是问题所在。现在我们放置结束标签并构建项目。设置结束标签后,我们可以成功查看storyboard。
When face any warning of conflicts , please compare with your previous source and changes source. We remove the old/redundant code , keep the new code with proper tag start-end and get things fixed.
当遇到任何冲突警告时,请与您之前的源进行比较并更改源。我们删除旧的/冗余代码,保留带有适当标记开始结束的新代码并修复问题。
[N.B , i will update the answer with some more test cases when get times]
[注意,我会在得到时间时用更多的测试用例更新答案]