【问题标题】:Xcode changes unmodified storyboard and XIB filesXcode 更改未修改的故事板和 XIB 文件
【发布时间】:2012-10-25 08:27:11
【问题描述】:

从 git 工作流程的角度来看,当多人协作时,故事板是相当痛苦的。例如,.storyboard 文件中的 XML 的起始 <document> 标记的 toolsVersionsystemVersion 属性会被最新的文件操纵器碰巧正在运行的任何配置更改。精确同步每个人的 Xcode 版本似乎对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 项目和 Git 并没有很好地结合在一起。除了丢弃不必要的更改之外,我认为您无法避免这种混乱——这些更改几乎总是对我来说是项目文件的更改,而我确定我没有更改其他 xml 文件。如果有任何“解决方案”,我会很高兴。我喜欢 Perforce,因为它方便的锁定功能不允许 Xcode 更改太多,这可能可以手动完成,用于您不会更改但仅用于查看的文件。
  • 不值得将故事板与 git 或其他任何东西一起使用。它们的设计初衷不是对提交友好。我们放弃并选择了 .xib,它也不是那么好,但至少它是细粒度的。
  • 我们发现故事板实际上可以很好地处理很多事情,尽管通常需要将它们与 XIB 混合使用。如果这个错误得到修复,我们会很乐意在绝大多数时间与他们合作。
  • 我只需要评论 ahwulf 的评论:你到底是什么意思他们不友好?它们是 XML/文本文件,这与您可以获得的提交友好度差不多。而且我对故事板和版本控制系统没有任何问题,唯一的问题当然是 xcode 有时会删除 标记,然后再读取它,但是如果您查看更改,您可以轻松看到这一点适用于任何 dvcs 的 git GUI 或 git -p 或等效项。我从来没有在 .pbxproj 文件中发生过这种情况,仅供参考。
  • 如果xcode可以通过读取类文件生成这些块,我无法理解为什么xcode将类块放在情节提要中?它们是一种“缓存”吗?如果是这样,它们应该放在 classes.cache 文件中,这样我们就可以将它从版本控制中排除...

标签: ios xcode interface-builder storyboard xib


【解决方案1】:

这不是错误,这是 Xcode 处理故事板文件的结果。 我正在为故事板文件(GitHub link) 编写一个差异和合并程序,我花了几个小时分析故事板文件逻辑以及 Xcode 如何处理它。这是我发现的:

  • 为什么故事板文件会发生奇怪的变化? Xcode 使用 NSXML API 将故事板文件解析为一些基于NSSet 的逻辑树结构。当 Xcode 需要编写更改时,它会根据逻辑树结构创建一个 NSXMLDocument,清除情节提要文件并调用 XMLDataWithOptions: 再次填充文件。因为集合不保留其元素的顺序,即使是最轻微的修改也可能改变整个故事板 XML 文件。

  • 为什么class标签会随机消失或重新出现? <class> 部分只不过是一个内部 Xcode 缓存。 Xcode 使用它来缓存有关类的信息。缓存经常更改。当 Xcode 怀疑它们已经过时(至少旧 Xcode 的行为是这样的)时打开和删除类 .h/.m 文件时添加元素。保存情节提要时,当前版本的缓存会被转储,这就是为什么<class> 部分经常更改甚至消失的原因。

我没有对 Xcode 进行逆向工程;我通过试验 Xcode 和 Storyboard 文件进行了这些观察。尽管如此,我几乎 100% 肯定它是这样工作的。

结论

  • 缓存部分不重要;您可以放心地忽略其中的任何更改。
  • 与您可以在所有论坛上找到的内容相反,合并故事板文件并不是一项复杂的任务。例如,假设您在故事板文档中更改了 MyController1 视图控制器。打开storyboard文件,找到类似这样的东西 <viewController id=”ory-XY-OBM” sceneMemberID=”MyController1”>。 您可以安全地只提交本节中的更改而忽略其他所有内容。如果您更改了 segues 或约束,也提交任何包含 “ory-XY-OBM” 的内容。简单!

【讨论】:

  • xcode diff/merge 工具有什么更新吗?听起来它对这个社区非常有用。
  • 您可以从我的网页上获取该应用程序(参见个人资料)。该应用程序是 100% 免费的。
  • 对我来说,尽可能多地拆分故事板 == 使用 XIB。如果你想把所有东西都切片,使用 XIB 更容易更好
  • “我没有对 Xcode 进行逆向工程;我通过试验 Xcode 和情节提要文件进行了这些观察。”这(浅)逆向工程,它是。 :-)
  • “这不是错误,这是 Xcode 如何处理故事板文件的结果。” 恭敬地,这句话的后半部分既没有解释也没有合理化前半部分。我将其修改为:“这是一个错误。这是 XCode 如何处理 .xib 文件的 [n 不幸的是未解决且非常烦人的] 结果。”从 XCode 5.x 到 6.2(今天,150311).xib 文件没有被开发人员修改,只是在 IB 中查看,遭受无故 xml 更改。这是一个影响生产力的严重错误。诸如“NBD,只需在 git 中处理块”之类的回答让我无语。
【解决方案2】:

这是 XCode 4.5+ 中的一个错误,我希望它得到修复,是的,它是一个 PITA。

这是 Apple 的完整错误

How to avoid Xcode gratuitous edits to storyboard files?

【讨论】:

  • 4.6 中的相同。也许这不是一个错误。
  • 4.6.3 仍然有它。不能说故事板/xibs 曾经运作良好
  • “这不是一个错误,它是一个特性”:-S
  • 没有证据表明这是一个错误 - 是的,令人烦恼,但这可能只是 Xcode 的工作方式
  • 7.0.1 并没有带来任何改变。
【解决方案3】:

在 Xcode 生成的任何文件(包括故事板、XIB、Core Data 模型和项目文件)上极其明智地使用 git add -p 可以在一定程度上缓解此问题,所有这些文件都遭受了类似的临时修改,但对实际的接口/模型/项目。

我在故事板上看到的最常见的垃圾更改是系统版本号(正如您提到的)以及不断添加和删除 <classes> 部分,我从未见过遗漏会导致问题。对于 XIB,这是对 <reference key="NSWindow"/> 的添加和删除,它甚至不是 Cocoa Touch 中的一个类。哇哦。

把它想象成大海:涨潮和退潮都有。让它冲刷你。

啊。就是这样。

您可以在暂存更改、重置垃圾更改并进行干净提交时忽略这些修改。

从技术角度来看,我所看到的故事板优于 XIB 的唯一优势是,Apple 尚未取消 FileMerge 以拒绝合并有冲突的故事板。 (FileMerge 曾经能够合并 XIB,但新版本打破了这一点。Thxxxx 伙计们?!!!)

请在http://bugreporter.apple.com/ 提交有关所有这些问题的大量错误!不要忘记在OpenRadar 上创建条目。

【讨论】:

    【解决方案4】:

    在这里抛出另一个答案,因为这种情况已经大大改善。表示 StoryBoard 的 XIB 文件的 XML 已大大简化。

    我最近也咬紧牙关,开始使用 Xcode 中的接口来进行源代码管理。我已经使用命令行多年并且在那里很开心,但是界面很好,它允许您拆分提交,如果您使用链接到提交的票务系统,这一点非常重要。

    无论如何,我今天注意到情节提要发生了变化,并且内置的差异显示它是文档标签(systemVersion)中的单个属性。所以没什么大不了的。

    我读过一些文章,其中有人说 SB 由于合并问题而在他们的团队中被取缔。彻底的疯狂。它们太棒了,尤其是现在它们内置了智能自动布局,如果你不使用它们,你真的会错过。

    【讨论】:

      【解决方案5】:

      了解为什么会发生这种疯狂是很有帮助的,但对于那些相信让他们的项目没有警告并且只想快速让他们的项目恢复健康的人来说状态:

      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. 忽略通过git checkout -- project.pbxprojproject.pbxproj 所做的更改。如果您git diff 该文件,您会看到它刚刚添加了有关我们的临时情节提要(不再存在)的信息。

      12. 打开 Xcode 备份并查看警告已消失。

      13. 呼吸。

      【讨论】:

        【解决方案6】:

        在同一个故事板上工作不是问题。但是在相同的视图控制器上工作会在拉/合并上产生冲突是可怕的。我们无法真正避免为大型团队在同一个视图控制器中工作。

        好消息是,如果我们了解 xml 结构,大多数时候我们可以修复相同的视图控制器冲突。在团队中工作时,我从来没有失败过合并这些。假设您正在使用视图控制器。您的视图当前为空白。请从源代码选项中查看视图控制器的 xml 结构。

        Storyboard 是由文档类型标签限定的 xml。情节提要中的所有内容都包含在场景 sceneID= 标签中。场景标签包含每个视图控制器。那是基本的。

        现在我们在视图上添加了一个 UILabel 和一个 UIButton。还要设置元素的自动布局。现在它看起来像:

        向视图控制器添加一个级别/按钮在视图的子视图标记内添加了一些新代码。同样的事情也适用于进一步的元素添加或任何 UI 更改。仔细检查标签结构,这对于解决任何冲突非常重要。

        现在我们在故事板名称 Homeviewcontroller 中添加另一个视图控制器。添加新的视图控制器意味着它在场景标签下添加了一个新场景。看看这个:

        此时,我们将随机更改结构并观察问题/警告。我们更改第一个 viewcontroller 标签结束标记并保存文件。现在运行它并查看警告。错误说从第 23 行创建的结束标签不正确。在第 23 行,我们看到标签约束设置为没有结束标签。那就是问题所在。现在我们放置结束标签并构建项目。设置结束标签后,我们就可以成功查看storyboard了。

        当遇到任何冲突警告时,请与您之前的来源和更改来源进行比较。我们删除了旧的/冗余的代码,用适当的标签开始新的代码并修复问题。

        [注意,我会在获取时间时用更多测试用例更新答案]

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-08-20
          • 2012-06-15
          • 2012-02-01
          • 2017-07-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多