This makes the 3rd post I’ve done tonight. I know that doesn’t mean anything to most people, but I started off trying to write a post on immediately invoked closures, I got sidetracked. twice.
Immediately Invoked Closures are also known in other languages as Immediately Invoked Functions or Immediately Invoked Function Expression (IIFE). But honestly, what we call them doesn’t really matter, it’s what they do.
Breaking down the term, Immediately Invoked might not be perfectly accurate, but the basic premise, goes like this
This is a closure
1 2 3 |
let c = { //do something } |
This is me executing the closure
1 |
c() |
This is how I could have done both steps at once
1 2 3 |
{ //do something }() |
In this case, it’s really an anonymous closure, so I don’t have a reference to just keep calling it over and over again, but that’s ok.
Immediately invoked closures can be very useful, even if they don’t seem like it at first. To start, let’s assume that we want to have an NSNumberFormatter with the currency style, we could do this
1 2 |
let formatter = NSNumberFormatter() formatter.numberStyle = .CurrencyStyle |
And it works just fine in some cases.
We could also do this
1 2 3 4 5 |
let formatter = { let f = NSNumberFormatter() f.numberStyle = .currency return f }() |
But this is more code, so why would we want to do this? Let’s suppose that we want to have the variable be on a class, and we don’t want to implement all 27 init methods (exaggeration, but I have had classes where I have to implement 3 different init methods)
This is invalid in Swift
1 2 3 4 5 |
class foo { let formatter = NSNumberFormatter() formatter.numberStyle = .CurrencyStyle } |
So at first glance, it would seem we would need to implement the init method to execute both lines
1 2 3 4 5 6 7 8 9 10 |
class foo { var formatter: NSNumberFormatter! = nil init() { formatter = NSNumberFormatter() formatter.numberStyle = .CurrencyStyle } } |
But this just has ugly written all over it. Also, if we add multiple init methods, we might have to start copying and pasting code. Depending on the superclass, you may even be required to implement a specific init method, but only if you implement any custom init methods. let’s look at this with immediately invoked closures
1 2 3 4 5 6 7 8 |
class foo { var formatter: NSNumberFormatter = { let f = NSNumberFormatter() f.numberStyle = .CurrencyStyle return f }() } |
No more init method. It’s like Christmas!
But what if we need to do something that requires a reference to another property? The easiest way to handle this is with a lazy property.
A lazy property will not have a value until it is accessed. When it is accessed, the initialization code we provide will be executed. There is a tiny performance overhead for a lazy variable, but just keep in mind that the performance associated with a single if statement is negligible in comparison to that of drawing a single pixel on the screen. The only time you should worry about this, is if you are working on some kind of game that has demanding algorithmic performance. Always favor maintainable code, unless you can’t. And even then, make it as maintainable as possible. You may remember how something works today, but that doesn’t mean future you will remember how something works.
To make it lazy, we just have to add the lazy keyword
1 2 3 4 5 6 7 8 |
class foo { lazy var formatter: NSNumberFormatter = { let f = NSNumberFormatter() f.numberStyle = .CurrencyStyle return f }() } |
Or if we need to access another property, we do something like this
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class foo { lazy var formatter: NSNumberFormatter = { [unowned self] in let f = NSNumberFormatter() f.numberStyle = .CurrencyStyle if(self.something) { //do something special } return f }() } |
We add the [unowned self] to ensure ARC is happy. It prevents our allocation block from having a strong reference to the class (which would create a retain cycle).
You can add lazy any time you want the property to be lazily instantiated, but if you instantiation closure references self , you the property must be lazy.
If you have a lazy property that doesn’t reference self, you can also just do this
1 |
lazy var blah: NSDateFormatter = NSDateFormatter() |
It’s only when you need to provide multiple lines of initialization code that you need to use an immediately invoked closure.
And there you have it. The single coolest thing I can think of in Swift. Immediately Invoked Closures and lazily instantiated properties.
Great article thanks! Quick question. The immediately executed closure combined with the lazy, i think i got it twisted.
Is the reason to use a immediately executed closure with a lazy, that the value will still be calculated first when you need it, and that the immediately executed closure makes sure that the actual return value of the closure is returned, and not the closure itself?
Yes. You are exactly correct