How to handle large Swift Project?

IosXcodeSwiftCompilation

Ios Problem Overview


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

  • 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.

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 DerivedData folder in RAM and periodically delete all files from it, it sometimes helps with SourceKit crashes.

Ios Solutions


Solution 1 - Ios

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

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

Slowness caused by immature Swift compiler

  • 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 without recompiling. 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 here for practical examples and here for 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 plugin to 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_OPTIMIZATION and set it to YES and at the same time set optimization level to none (to disable optimizations that would make it slow) OUTDATED You 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)

  • OUTDATED Try 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).

  • OUTDATED Try this hacked up incremental compilation technique

UPDATE: Incremental builds introduced on 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.

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)

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.

  • 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.

Solution 2 - Ios

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

Remove all type inferences in Swift.

This SO topic has some nice ideas and this blog post suggest to

  1. stop generating dSYM bundles and
  2. avoid compiling with -O4 if using Clang.

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

Solution 3 - Ios

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

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.

Solution 4 - Ios

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...

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

Solution 5 - Ios

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.

Solution 6 - Ios

In my experience avoid creating the large swift files, when I started a project in my new company, there was a 'UIViewController' with more than 2000 lines, little changes on this file taking much time to build, I made 4 extensions with <500 lines from that class, my speed improvement was incredible.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlexey GlobchastyyView Question on Stackoverflow
Solution 1 - IosDanieleView Answer on Stackoverflow
Solution 2 - IosMichael DornerView Answer on Stackoverflow
Solution 3 - IosMirekEView Answer on Stackoverflow
Solution 4 - IosMoralCodeView Answer on Stackoverflow
Solution 5 - IosbzzView Answer on Stackoverflow
Solution 6 - IosHamedView Answer on Stackoverflow