xcode 如何处理大型 Swift 项目?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28032506/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 06:30:55  来源:igfitidea点击:

How to handle large Swift Project?

iosxcodeswiftcompilation

提问by Alexey Globchastyy

After iPhone app that I'm writing in Swift become quite big (> 150 .swift files + various Objective-C libs), Xcode start behave pretty badly:

在我用 Swift 编写的 iPhone 应用程序变得相当大(> 150 个 .swift 文件 + 各种 Objective-C 库)之后,Xcode 开始表现得非常糟糕:

  • every second compilation I get various errors, e.g.:

    Command failed due to signal: Segmentation fault: 11

  • compilation take enormous amount of time (> 2 min on MacBook Pro Retina)
  • and so on.
  • 每次编译我都会收到各种错误,例如:

    Command failed due to signal: Segmentation fault: 11

  • 编译需要大量时间(在 MacBook Pro Retina 上需要 2 分钟以上)
  • 等等。

I just wonder if everyone has same problems and maybe someone found a way to reduce this nightmare?

我只是想知道是否每个人都有同样的问题,也许有人找到了减少这种噩梦的方法?

What I have done so far — I split project into several dynamic frameworks that I link from main project, it helps to reduce compile time, but introduce some new problems.

到目前为止我所做的 - 我将项目拆分为几个动态框架,从主项目链接,这有助于减少编译时间,但引入了一些新问题。

I also use iRamDisk to keep DerivedDatafolder in RAM and periodically delete all files from it, it sometimes helps with SourceKit crashes.

我还使用 iRamDisk 将DerivedData文件夹保存在 RAM 中并定期从中删除所有文件,它有时有助于解决 SourceKit 崩溃。

回答by Daniele

Swift toolchain is still a bit gross, you'll need to use some temporary workarounds until Apple fixes it (see UPDATESbelow)

Swift 工具链仍然有点粗糙,您需要使用一些临时解决方法,直到 Apple 修复它(请参阅下面的更新

Here is a list of items that you can do to keep yourself from going crazy.

这里列出了一些您可以做的事情来防止自己发疯。

Slowness caused by immature Swift compiler

不成熟的 Swift 编译器导致的缓慢

  • Change your development workflow using Injection for Xcode. Once you installed the plugin, you'll be able to inject code changes in your simulator\device withoutrecompiling. You don't need to hardcode\modify anything in your project. We started using it recently at work and it made a huge impact on our side, even if it doesn't apply to every use case (for example you can't create new functions, you can only modify the existing ones).

  • Some particular code constructs that the compiler doesn't like and takes too much time to compile. The most common problem is with the Type Checker that slows down compile time exponentially based on how many type checks it needs to do (read more herefor practical examples and herefor a detailed explanation). In order to identify if you are suffering from this problem you can follow this blog post, you will gather information about the functions that creates slowness by using some compiler additional flags. Alternatively you can use this Xcode pluginto identify the source of the build slowness.

  • Use dynamic frameworks wisely, where it makes sense. A framework recompilation will be done only when you modify one of its Swift files (dynamic frameworks are only available for iOS >= 7).

  • Condense code in the same files. Lowering the number of Swift files speeds up the compile process sensibly. You can easily achieve it enabling "Whole module optimization" by adding an user-defined custom flag SWIFT_WHOLE_MODULE_OPTIMIZATIONand set it to YES and at the same time set optimization level to none (to disable optimizations that would make it slow) OUTDATEDYou may consider to use this gist, it's a build script that collapses all your code in a "merge.swift" file. You'll need to create a new target for it, but it is worth a try.

  • Double check things listed here(there are a few some more misc reasons because the compilation is slow)

  • OUTDATEDTry the approach described in this blog post, it involves creating a build script that generates a make file. It requires manual intervention on the build script (it contains the list of swift files).

  • OUTDATEDTry thishacked up incremental compilation technique

  • 使用Injection for Xcode更改您的开发工作流程。安装插件后,您将能够在模拟器\设备中注入代码更改,而无需重新编译。您不需要对项目中的任何内容进行硬编码\修改。我们最近开始在工作中使用它,它对我们产生了巨大的影响,即使它不适用于每个用例(例如,您无法创建新功能,只能修改现有功能)。

  • 编译器不喜欢某些特定的代码构造并且需要太多时间来编译。最常见的问题是类型检查器会根据它需要执行的类型检查数量成倍地减慢编译时间(在此处阅读更多实际示例,在此处阅读详细说明)。为了确定您是否遇到此问题,您可以关注此博客文章,您将通过使用一些编译器附加标志来收集有关造成速度缓慢的函数的信息。或者,您可以使用此Xcode 插件来确定构建缓慢的来源。

  • 在有意义的地方明智地使用动态框架。仅当您修改其 Swift 文件之一时才会进行框架重新编译(动态框架仅适用于 iOS >= 7)。

  • 压缩相同文件中的代码。减少 Swift 文件的数量可以显着加快编译过程。您可以轻松地实现它使“整个模块优化”通过增加一个用户自定义的标志SWIFT_WHOLE_MODULE_OPTIMIZATION并将其设置为YES,并在同一时间设置优化级别为none(禁止优化,将使其慢)过时您可以考虑使用这个gist,它是一个构建脚本,可将您的所有代码折叠在“merge.swift”文件中。您需要为它创建一个新目标,但值得一试。

  • 仔细检查此处列出的内容(由于编译速度慢,还有一些其他原因)

  • 过时试试这篇博文中描述的方法,它涉及创建一个生成生成文件的构建脚本。它需要对构建脚本进行手动干预(它包含 swift 文件列表)。

  • 过时试试这个黑客增量编译技术

UPDATE: Incremental builds introduced on Swift 1.2 (Xcode 6.3)

更新:在 Swift 1.2 (Xcode 6.3) 上引入增量构建

Apple finally introduced incremental builds with Swift 1.2 (shipped with Xcode 6.3). It's not still perfect, but it's a huge improvement.

Apple 终于在 Swift 1.2(Xcode 6.3 附带)中引入了增量构建。它仍然不是完美的,但它是一个巨大的改进。

From now on a class is recompiled only when it is changed (or when one of the class it depends on has been changed). However the compiler still can't understand if the changes to a class are to its interface or not. So any kind of change to a class causes a recompilation of that class and all of its dependencies.

从现在开始,一个类只有在它被改变时(或者当它所依赖的一个类被改变时)才会被重新编译。然而,编译器仍然无法理解对类的更改是否针对其接口。因此,对类的任何更改都会导致对该类及其所有依赖项进行重新编译。

UPDATE: Recompile dependent classes only when public interface changes introduced on Swift 2.1 (Xcode 7.1)

更新:仅在 Swift 2.1 (Xcode 7.1) 上引入公共接口更改时重新编译依赖类

Starting from Swift 2.1 (Xcode 7.1), the dependent classes are recompiled only when you change the public interface of a class, and not at every change. This makes an huge difference in particular for big projects.

从 Swift 2.1 (Xcode 7.1) 开始,依赖类仅在您更改类的公共接口时重新编译,而不是在每次更改时重新编译。这对大型项目尤其如此。

Project (mis)configuration (not related to Swift)

项目(错误)配置(与 Swift 无关)

  • Be sure that "Build Active Architecture Only" is YES for debug.
  • Be sure that you didn't add pre\post compilation scripts that take too much time.
  • 确保调试时“仅构建活动架构”为“是”。
  • 确保您没有添加花费太多时间的前\后编译脚本。

回答by Michael Dorner

Apple has some advices for speeding up your Xcode build in Technical Note 2190. Have you thought about creating and precompiling an own frameworkfor outsourcing unchanged Swift modules or some/all Objective-C code?

Apple 在Technical Note 2190 中提供了一些关于加速 Xcode 构建的建议。您是否考虑过创建和预编译一个自己的框架来外包未更改的 Swift 模块或部分/全部 Objective-C 代码?

Remove all type inferences in Swift.

删除 Swift 中的所有类型推断。

This SO topichas some nice ideas and this blog postsuggest to

这个 SO 主题有一些不错的想法,这篇博文建议

  1. stop generating dSYM bundles and
  2. avoid compiling with -O4if using Clang.
  1. 停止生成 dSYM 包和
  2. -O4如果使用 Clang ,则避免编译。

Although lots of these improvements are related to Objective-C, I am quite sure, that some of them are still relevant for Swift.

尽管这些改进中有很多都与 Objective-C 相关,但我很确定,其中一些改进仍然与 Swift 相关。

回答by MirekE

The (re)compiling is a known issue that I am sure will be resolved soon. Some recommendations:

(重新)编译是一个已知问题,我相信很快就会解决。一些建议:

  • Use Objective C where possible - it compiles fast even if it is a part of a Swift project
  • Split code to frameworks
  • Specify types instead of leaving it up to the compiler to infer them
  • 尽可能使用 Objective C - 即使它是 Swift 项目的一部分,它也能快速编译
  • 将代码拆分为框架
  • 指定类型而不是让编译器来推断它们

Again, there is a good chance that this will be fixed soon, so perhaps it is best not to make big investments in rewriting or reorganizing the code at this point in time.

同样,这很有可能很快就会得到修复,所以此时最好不要在重写或重新组织代码方面进行大量投资。

回答by MoralCode

you could try:

你可以试试:

  • upgrading the amount of RAM in your computer
  • if you have multiple .swift files that do things on the same view controller, try condensing them into one .swift file per view controller
  • tweaking the settings under compile sources to see if you have any duplicates or if there are any scripts or settings you can add to make it compile faster...
  • 升级计算机中的 RAM 量
  • 如果您有多个 .swift 文件在同一个视图控制器上执行操作,请尝试将它们压缩为每个视图控制器的一个 .swift 文件
  • 调整编译源下的设置以查看是否有任何重复项,或者是否可以添加任何脚本或设置以使其编译速度更快...

you can also take a look at thispost's answers for some hints as to what you can do to slow down compile time

您还可以查看这篇文章的答案,以获取有关如何减慢编译时间的一些提示

回答by bzz

I've discovered that one of the main causes of segmentation faults and slow compilation is hardcoding big arrays and dictionaries, especially when declaring them as global constants and trying to access values from them from within another .swift file. When I store all that data inside plists, these problems are gone.

我发现分段错误和编译缓慢的主要原因之一是硬编码大数组和字典,尤其是在将它们声明为全局常量并尝试从另一个 .swift 文件中访问它们的值时。当我将所有数据存储在 plist 中时,这些问题就消失了。