Improve build times in Swift with Xcode

2 minute read

While sipping refreshment, I glanced at the activity view bar as Xcode was building project. I saw that until compilation finishes I will gulp another glass. Was the size of the code base stretching the compiler limits? Why the Xcode got stuck at indexing?

As I was coding a new feature, I needed fast feedback from the compiler. With the subsequent builds, seconds added up to minutes. The sluggishness was derailing my workflow.

Quick builds guarantee we use our time and money efficiently, they prevent distractions and make the work a pleasure. Test Driven Development requires quick builds. Rapid builds save time and sanity when running tests again and again. I imagined compilation times not in minutes but in seconds. How would that speed up my work and increase our team response to bugs?

Profiling

Xcode gives a way to find code lagging the compiler. Here’s how profile your app.

In project Build Settings under Swift-Compiler - Custom Flags, Other Swift Flags add:

Experiment with the 100 argument. If compiler goes beyond the specified millisecond limit, Xcode will warn you and show you the offending place.

Improving

How to improve build times? The easiest way:

  • Use explicit types for complex properties. You save the time for the compiler to figure out the type. And you save your colleagues time on figuring out the type of the property.
  • Provide types in complex closures.

  • Don’t use + to concatenate a strings.
  • Precompute. Never do computations directly from the if-else conditions.
  • Dependencies within a module are per-file. Dependencies across targets are for the entire target.

  • Incremental Builds are file-based. Unrelated changes outside function bodies can still result in rebuilding. If you change the function bodies then other files won’t be recompiled, as changes in function bodies do not affect the file’s interface.
  • Limit your objective-C/Swift interface. Keep your generated header minimal. User private when possible:
    • Make IBOutlet private and IBAction private.
    • Make methods exposed to Objective-C @objc private. Or you can switch to block based APIs, which may additionally cleanup your code.

Depending on your project and your needs, your can do more. Be sure to watch:

Sources: