Codable data struct is persisted, then I need to add more fields to the struct. How can I do this? Is there any good way to migrate
Codable from one version to another? I think I need to at least have a version field in my struct?
I don't think there's a one-for-all solution, it really depends on the use case. You could add a version field — but that one would obviously need to be encoded too, which could be very costly in case of collections (for a collection of 100 items of the same version, you would have 99 redundant fields re-stating the same version information). It also depends on whether you control the other party too: what if you bump up the version on, say, the sending side, but the receiver doesn't know how to handle this? Having a default value could help in this case, but again, it depends on whether you even allow having that default value.
If you say that your data already persists somewhere (on a user's hard drive, say) and you haven't explicitly written the version alongside, then perhaps your best bet is to write some small function that would try to check a subset of that data (just one element instead of the whole collection, for example) and retroactively decide if there's enough information to be decoded into the new version.
Anyways, it's hard to tell without seeing a more concrete example, but my sentiment is the same: I can't think of a way to arbitrarily manipulate encodings without additional effort.
I was hoping to see some examples. Anyway, my inside my head thinking:
- Store the version number separately
- Ib load, readd this version number first, if the version is not current, then load via old version Codable struct, migrate this to the current Codable struct, persist back out in new version.
The way that I have done it is to always output all of the fields unconditionally for encode. For decode I use decodeIfPresent and default (nil coalesce) to a reasonable value if the key is not present. If all of the changes are additive, this strategy works well, I think. It has the nice property that it is forward and backwardly compatible if you don't change the semantic meaning of the fields being saved.