The Current Standard
In our Swift codebase, we make extensive use of the “closure initialisation” standard. For example, instead of writing this:
We would write this:
It’s a good standard, one with many advantages. For example, it provides a clear, single location in the code where most, if not all, of the configuration for a particular UI element is done.
However, as you may have noticed, we are forced to write out the type of the variable twice — once to declare the type of the variable and once to initialise its value.
This may be desired in some cases. The external-facing type being separated from the internal type, in combination with polymorphism (either through subclassing or through protocols), allows us to declare variables using the most useful general type and hide the specifics of the actual type to any clients. I might, for example, declare a
UILabel property but initialise the value with an instance of my own
FancyLabel subclass. Or, I might declare the property to be
UITableViewDataSource and interchangeably use various conforming types as the actual value, without having to worry about how that affects clients of the property.
However, in practice, we don’t often get this advantage; we usually declare and initialise exactly the same type. If you create enough variables in this standard, it starts to get a little tedious. Furthermore, when using a type that is already tedious to type out, the tedium doubles. For example, try declaring a couple of these variables:
How about a more finger-friendly standard?
Looking at the Issue
We want to combine the advantage of not using the closure initialisation standard — namely, the ability for a variable’s type to be inferred from its initialisation — with the advantages of the standard — such as the ability to perform the configuration of an object as part of its declaration.
We already have a pattern for what this could like, courtesy of Swift’s semi-functional paradigm. This paradigm allows us to replace a multi-statement sequence such as this:
So taking our cue from this type of syntax, I propose we add a
configured method to the types of variables we would like to configure upon declaration. It should be basically like being able to
map over a single variable. So let’s dig in!
Adding the Configuration Method
Our configuration method will be very simple, and the implementation will be the same for all types. An easy way to add a method to arbitrary types is to declare a protocol, then extend that protocol with the method to add:
Any type can now get this method for free by just conforming to
InlineConfigurable. Let’s extend
Just like that, most of the types provided by the various iOS SDKs are magically configurable. If we want this functionality for types we define ourselves, we can either inherit them from
NSObject or simply conform them to
And finally, here is how we use it:
UPDATE 9 August 2019
I made a CocoaPods version of this. It’s called PHBApplying, and you can use it like this:
I changed the name from
applying because, as Maciej Najbar pointed out in the comments, this concept is called
apply in Kotlin (thanks Maciej!)
I also discovered that this concept has already been implemented as a CocoaPod called Then. Their existing implementation is a notch above my own, but I disagree with the naming, because
then is commonly associated with asynchronous operations.
Thanks for reading!