This source has a paragraph Setting a Default Property Value with a Closure or Function where we can find an example
Here’s a skeleton outline of how a closure can be used to provide a default property value:
class SomeClass { let someProperty: SomeType = { // create a default value for someProperty inside this closure // someValue must be of the same type as SomeType return someValue }() }
Well, I use it very often... Also, I often wait for the whole project to recompile after changing just one symbol. And today I have discovered that these two things are associated to each other.
Lets imagine we have some class where we set some default properties with a closure and with a function
class Class1 {
let value: Int
init(_ value: Int) {
self.value = value
}
private lazy var lazyValueWithClosure: Int = {
return 1111
}()
private lazy var lazyValueWithFunction: Int = self.getValue()
private func getValue() -> Int {
return 2222
}
}
Also we have some other class in a separate file where we use the above Class1
class Class2 {
let value: Int
init(_ value: Int) {
self.value = value
_ = Class1(100)
}
}
And some other class in a separate file where we use Class2
class Class3 {
let value: Int
init(_ value: Int) {
self.value = value
_ = Class2(100)
}
}
and etc...
I've decided to use terminal
+ xcodebuild
+ grep
to get only info about recompiled files. That is the command I use to get compilation info:
xcodebuild -scheme Test -sdk iphonesimulator -arch x86_64 -configuration Debug build OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" | grep '^[0-9]\{1,20\}.[0-9]\{1,20\}ms.*init(_ value: Int)'
That is all for preparations. Now we go to Class1
and change 2222
to some other value. Run the above command and get a result.
0.1ms /Users/iwheelbuy/Documents/recompile/Test/Classes/Class1.swift:11:5 init(_ value: Int)
The result is good. Setting default value with functions works as expected. We have changed one file and only one file was compiled.
Then lets change the value 1111
from the Class1
to some other value and run the command. Terminal output now looks like this:
0.8ms /Users/iwheelbuy/Documents/recompile/Test/Classes/Class5.swift:11:5 init(_ value: Int)
0.3ms /Users/iwheelbuy/Documents/recompile/Test/Classes/Class1.swift:11:5 init(_ value: Int)
1.0ms /Users/iwheelbuy/Documents/recompile/Test/Classes/Class4.swift:11:5 init(_ value: Int)
0.3ms /Users/iwheelbuy/Documents/recompile/Test/Classes/Class3.swift:11:5 init(_ value: Int)
0.3ms /Users/iwheelbuy/Documents/recompile/Test/Classes/Class2.swift:11:5 init(_ value: Int)
All the classes were recompiled... Now imagine that you have a large project and any small change in a default value closure makes you wait for the whole project to recompile.
Questions:
This is a known problem in the Swift compiler. The issue is that once you use closures or lazy properties like this, every single Swift file will be type checked. I've written a blog post on this topic which you can find here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With