Immutability is a very desirable property of our data structures. It means that the internal state of our instances does not change after their creation. It has multiple benefits, ranging from thread-safety to being easier to reason about them.
Swift even encourages developers to make data structures immutable. For instance,
structs are, by default, immutable, and methods that alter the internal state of a
struct must be marked with the
However, sometimes we need to make changes to the state of an object. In such case, the recommendation is to create a new instance of an object, with the appropriate modifications. Languages like Kotlin or F# provide methods to do that. In Kotlin, for instance, you have a
copy method where you can pass named arguments matching the fields you want to modify, and it will return a copied instance with the same fields as the original one, and the changes you set in the call arguments.
Unfortunately, Swift does not have this feature by default, but luckily for us, it can easily be added.
Adding a copy method
Let’s assume we have the following data structure:
We can create a method to return a copy of this object, with some modifications, as follows:
The recipe is straightforward:
- Create a
copymethod that returns a new instance of its type.
- Add an argument to the
copymethod for each field in the class/struct.
- Make the type of each argument optional.
nilas the default value of each parameter.
- In the body of the method, just return a new instance, choosing the arguments that were sent to the
copymethod, or the existing values if they were not set (using the ?? operator).
Removing the boilerplate
As you can see, the procedure is really simple but involves writing some boilerplate. However, we can get rid of it. If writing the
copy method is so automatic, let’s automatize it with an Xcode Source Extension!
I have created and open-sourced such an extension, which will allow you to select the fields of a class or struct, and generate both a constructor (
init method) and a copy method, automatically. You can find it in my Github account.
Working with the extension still has some limitations; for instance, if you add new fields to your data structure, you will have to delete and recreate the generated code. Nevertheless, I still find it useful to save me from writing some boilerplate - and I hope you can find it useful as well.
Tomás Ruiz-López DEVELOPMENT
swift iOS Kotlin boilerplate Xcode Source Extension