Article

Fixing issues with Codable identifiers

Mason O'Neil

July 24, 2020

Experiencing an issue with property values changing after encoding and decoding a Codable object? You may have run into the same problem I had with setting identifiers using UUID().uuidString as the initial value.

The Problem

Say you have a Codable object that generates its own identifier like so:

Generating the UUID inline will create a new unique identifier every time a new Employee object is instantiated. Perfect! However, the value present when you encode won’t be the same value you get back when you decode.

The Cause

Because the identifier property is declared as a let with a default value, the non-mutable property cannot be assigned a new value. Codable is ultimately initializing your object using a Decoder . You can recreate this problem by creating your own initialize from decoder method, like so:

Notice how the above example does not compile with the following error: “Immutable value ‘self.identifier’ may only be initialized once”. Because the non-mutable identifier property already has a value assigned, UUID().uuidString , it cannot be assigned the value from the decoded container.

Solutions

Make the property mutable:
The most simple and straight forward workaround is to declare the identifier property as a mutable var . This will allow the initializer to override the default value with the value in the decoded container.

In Xcode 12, a new compile time warning is issued when using a non-mutable property and initial value on an object that implements the Decodable protocol: “Immutable property will not be decoded because it is declared with an initial value which cannot be overwritten. Make the property mutable instead”

Set the initial value in a constructor:
If you do not want to make the property mutable, another option is to set the initial value for the identifier property within a constructor. Like so:

Because the non-mutable identifier property no longer has an initial value by default, the initializer used by Codable can successfully set the value to the value in the decoded container.

This is the solution our team ended up using. We felt that it was better to keep the identifier property non-mutable and set the value within a custom initializer that already existed.



Mason is an iOS developer social distancing with his dog at Livefront