Kotlin-Style Copy Function For Swift Structs
Article Summary
Scott Birksted from Shopify tackles a frustrating gap between Kotlin and Swift: why can't Swift structs copy themselves as elegantly as Kotlin data classes?
When Shopify's mobile team tried bringing Kotlin's immutable state pattern to iOS, they hit a wall. Swift structs lack the convenient .copy() function that Kotlin developers take for granted. This article walks through the evolution of a solution, from basic workarounds to an automated approach using code generation.
Key Takeaways
- Swift loses its default initializer when you set property defaults or define custom init
- Optional properties break simple copy functions (nil means preserve, not clear)
- Builder pattern with closures solves the optional property problem elegantly
- Sourcery code generator automates all boilerplate with a reusable stencil template
- Extension-based init preserves compiler-generated default initializer
A builder pattern combined with Sourcery code generation brings Kotlin-style immutable state management to Swift without manual boilerplate.
About This Article
Swift structs don't have Kotlin's .copy() function, so developers end up writing a lot of boilerplate code when they need to create modified copies of immutable state objects. This is especially tedious when working across both iOS and Android codebases.
Scott Birksted's team built a functional builder pattern using closures to capture property overrides. They then automated the whole thing with Sourcery code generation, using a reusable stencil template to handle the repetitive work.
Any struct marked with @AutoCopy now gets initializers and builder structs generated automatically by the Sourcery template. This cuts out the manual boilerplate while keeping the same immutability patterns that Kotlin developers are used to.