Understanding the Mutating Keyword in Swift
When it comes to managing objects in Swift, Apple’s recommendation is to use a Struct over a Class where you can for easier memory management not only for the developer, but for the health of the app. Structs are value types, meaning they are allocated to the device’s heap, and do not have a reference pointer in memory and are optimized for speed.
Imagine we are working on an app that captures user information. Our data model is a simple Struct named User that takes a firstName and lastName at initializtion.
Our apps logic requires us to ensure each user has a capitalized firstName and lastName. Since we want our data model to manage its own properties we will write a method to make sure the entered information is configured correctly.
Now it is as simple as calling our properties .capitalized properties making our User object ready for use!
When we try to manipulate our properties we get an error. What is going on here? The error message reads: Cannot assign to property: ‘self’ is immutable. A Struct’s properties are immutable from within the Struct itself, in other words Swift cannot infer if the Struct will be declared as a variable or a constant when created, so be safe Swift does not allow any changes to a Struct’s properties from within its methods.
Luckily Swift provides us with a keyword allowing us to work with these immutable properties. The Mutating keyword flags our function with the ability to work with our properties as variables, allowing us to capitalize our strings.
It’s important to know that our Struct’s properties are still immutable, so why does the Mutating keyword allow us to manipulate our properties? Under the hood Swift makes a new copy of our Struct and assigns our new values to its properties. The original Struct we defined is then replaced by our copied struct. Since Structs are value types, they are always copied when they are assigned to new variables or constants and do not contain a reference to a specific spot in memory.
You can see the mutating keyword throughout Swift. A common place is in the native Array type. Once an array is declared, there is no way to simply assign it more space to hold more items. The Array’s methods that manipulate the contents of the Array are all Mutating functions.
While we cannot add more space to this collection of data, the append() method can add the new element to the Array, then copy all of its contents into a new array.
Now I know what you’re thinking,”Why not simply capitalize the User’s properties in an init method or why not use dot notation directly to manipulate its properties?” While this is an overly simplified example, data in the real world might need to be changed at a later time, not right at intializtion. The Mutating keyword can make managing Structs easier by allowing their methods to manage the state’s of its own properties, allowing for less clutter using dot notation throughout your code.