Swift Compile Time Tuneup

As our Swift projects are getting bigger, we noticed that the compile time was way above what one would call acceptable. I'm talking in range of ~25 min for clean build.

After some investigation, we realize that there are two major problem groups, one was Cocoapods, and other was Swift syntax.

Bellow you can find some issues and how to resolve them. Also this isn't silver bullet, so the best way is to do it gradually and measure intermediate state.

Common issues

Complex expressions, e.g.

Bad

let x = ["A", nil, "B", nil,"C"].flatMap{$0}.reduce("", +)

Good

let x: String = ["A", nil, "B", nil,"C"]
    .flatMap { letter -> String? in
        return letter
    }
    .reduce("") { (accumulator, nextItem) -> String in
        return accumulator + nextItem
    }

Concatenation of string:

Bad

let greeting1 = "Hello, \(firstName) \(lastName)!"
let greeting2 = "Hello, " + firstName + " " + lastName + "!"

Good

let greeting = String(format: "Hello, %@ %@!", firstName, lastName)

Literal array build

Bad

let x = [
    CellItem(name: "A", count: 23, selected: false, actionHandler: {}),
    CellItem(name: "B", count: 12, selected: true, actionHandler: {}),
    CellItem(name: "C", count: 15, selected: true, actionHandler: {}),
    CellItem(name: "D", count: 44, selected: false, actionHandler: {}),
]

Good

var x = [CellItem]()
x.append(CellItem(name: "A", count: 23, selected: false, actionHandler: {}))
x.append(CellItem(name: "B", count: 12, selected: true, actionHandler: {}))
x.append(CellItem(name: "C", count: 15, selected: true, actionHandler: {}))
x.append(CellItem(name: "D", count: 44, selected: false, actionHandler: {}))

Above mentioned problems may or may not affect your build time, the only way to be sure of this is to actually measure how long does it take for each method call to compile. If you ask yourself how to do it, scroll to the bottom ;)

Cocoapods

post_install do |installer|
  puts "********** PODS POST INSTALLATION HOOK **********"
  puts "Updating **BUILD SETTINGS** key **DEBUG_INFORMATION_FORMAT** for **ALL PODS** to allow faster build time by changing **DWARF with dSYM** to **DWARF** when in **DEBUG** ... "
  installer.pods_project.targets.each do |target|
      target.build_configurations.each do |config|
      if config.name =~ /Debug/
          # This adds the flag to the Pods.xcodeproj itself at the most local level (basically per **Pod**)
          config.build_settings['DEBUG_INFORMATION_FORMAT'] = 'dwarf';
      end
    end
  end
end

Global project compile time:

$ defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES

Compile time per method call:

iOS Methods Compile Time