Swift: Configuring a Constant Using Shorthand Argument Names
There is a tweet going around on initializing constants in Swift using positional references:
Just learned from .@ericasadun's Github that I can initialize a constant using positional references! š #swiftlang pic.twitter.com/KzhXhPliWV
— Nicholas Sakaimbo (@nick_skmbo) May 24, 2016
The original code is here.
Since it is an ephemeral tweet, and I was confused when it didn’t work as I expected on first glance, I wanted to write a more permanent blog post on the topic here.
The Problem
It’s a common pattern in Swift (and a really nice one!) to configure constants right when they are initialized in a closure vs later on in a viewDidLoad or another such method:
1 2 3 4 5 6 7 |
let purpleView: UIView = { // have to initialize a view here // is "view" the correct name for it? let view = UIView() view.backgroundColor = .purpleColor() return view }() |
I’ve always found it kind of awkward to name another UIView in the closure. Now there is a “purpleView” and a “view”. Should “view” actually be named “purpleView” also? I haven’t figured out a good solution for the naming problem here.
The Solution
So I was super excited to see the tweet that uses $0 instead of bothering to name the variable! I immediately tried it like this:
1 2 3 4 5 |
// spoiler: this does not work... let yellowView: UIView = { $0.backgroundColor = .yellowColor() return $0 }() |
But it didn’t work… Upon closer inspection of @ericasadun’s code, I learned that I had to pass in the initialized UIView when the closure is executed:
1 2 3 4 5 |
let yellowView: UIView = { $0.backgroundColor = .yellowColor() return $0 // make sure to pass in UIView() here! }(UIView()) |
This of course makes a lot of sense!
Conclusion
I do really like the idea of using $0 here instead of explicitly naming the thing, but I’m upset that it didn’t come naturally to me. However, now that I know I have to pass in an initialized UIView() in there, it does logically make sense. I think I’ll use this in the future. Getting to use $0 here is just too beautiful not to!
Join me for a Swift Community Celebration š in New York City on September 1st and 2nd. Use code NATASHATHEROBOT to get $100 off!
Update
As @khanlou pointed out, there is a super cool library called Then to make this even more readable and better:
1 2 3 4 5 |
let label = UILabel().then { $0.textAlignment = .Center $0.textColor = .blackColor() $0.text = "Hello, World!" } |
While I’m not a fan of adding this library as a dependency to my project, @khanlou pointed out once again that it’s only 15 lines of code. So I’ll definitely consider copying this over manually into my project!
Make sure to also check out @ericasadun’s nice solution!