Faster preview with SwiftUI, Text formatting
By: Andrey Á Perv
Tags: Swiftui, Text, Canvas

In the previous topic I was talking why we should use modular project architecture in order to get benefits from working with SwiftUI.

Once we cut dependencies from the module with SwiftUI we gain significant boost in preview performance, we also should look on the SwiftUI code.

SwiftUI is swift code (obvious) and it follow same rules regarding compile time optimisation. If note done yet, you can read e.g. here: https://medium.com/rocket-fuel/optimizing-build-times-in-swift-4-dc493b1cc5f5.

For us we will focus on adding to the project:

-Xfrontend -warn-long-function-bodies=200

After it you may notice that swift often have hard time e.g. checking type of math operation with optional variables like:

a + b ?? 0 + c ?? 0

I will update this article with different code that significantly impact build time without many reasons. So here is one:

1. Never use Text() +

Some of the task may require show long static formatted texts. And first we can do is concat Text with <+> like:

Text(“Lorem ipsum dolor sit amet,”).foregroundColor(.blue) + Text(“consectetur adipiscing elit,”).foregroundColor(.blue) + Text(“sed do eiusmod tempor incididunt”).foregroundColor(.blue) + Text(“ut labore et dolore magna aliqua.”).foregroundColor(.blue)

Instantly got a warning: “Getter ‘body’ took 563ms to type-check (limit: 200ms)”. And by adding few more will get: “The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions”

Instead of <+> I suggest using an extension:



extension Text { static func joined(_ texts: [Text], separator: Text) -> Text { var text = Text(“”) for (index, item) in texts.enumerated() { text = text + item if index < texts.count — 1 { text = text + separator } } return text } }

And now let’s adjust our warning threshold to 1 ms and test much longer code:

Text.joined([ Text(“Lorem ipsum dolor sit amet,”).foregroundColor(.red), Text(“consectetur adipiscing elit,”).foregroundColor(.green), Text(“sed do eiusmod tempor incididunt”).foregroundColor(.blue), Text(“ut labore et dolore magna aliqua.”).foregroundColor(.red), Text(“Ut enim ad minim veniam,”).foregroundColor(.green), Text(“quis nostrud exercitation”).foregroundColor(.blue), Text(“ullamco laboris nisi”).foregroundColor(.red), Text(“ut aliquip ex ea”).foregroundColor(.green), Text(“commodo consequat.”).foregroundColor(.blue), Text(“Duis aute irure”).foregroundColor(.red), Text(“dolor in”).foregroundColor(.green), Text(“reprehenderit”).foregroundColor(.blue), Text(“in voluptate velit”).foregroundColor(.red), Text(“esse cillum”).foregroundColor(.green), Text(“dolore eu fugiat”).foregroundColor(.blue), Text(“nulla pariatur.”).foregroundColor(.red), Text(“Excepteur sint o”).foregroundColor(.green), Text(“ccaecat cupidatat”).foregroundColor(.blue), Text(“non proident,”).foregroundColor(.red), Text(“sunt in”).foregroundColor(.green), Text(“culpa qui”).foregroundColor(.blue), Text(“officia deserunt”).foregroundColor(.red), Text(“mollit anim”).foregroundColor(.green), Text(“id est laborum.”).foregroundColor(.blue) ], separator: Text(“”))

Got a warning: “Getter ‘body’ took 5ms to type-check (limit: 1ms)”.

Well, I can live with that.