Skip to content
tezvyn:

Explain Copy-on-Write in Swift and implement it for custom structs

Source: developer.apple.comHardHow cards are made

Explain Copy-on-Write in Swift and implement it for custom structs

Tests value semantics with reference storage and uniqueness checks. A strong answer explains CoW delays copy until mutation via isKnownUniquelyReferenced, lists custom steps: wrap, read, check, clone. Red flag: assuming structs are automatically CoW.

What's really being asked

This question probes your understanding of value semantics versus reference semantics, and specifically how Swift achieves performant value semantics for large collections. The interviewer wants to see that you know Swift arrays and dictionaries do not copy their entire backing store on every assignment, and that you can manually implement the same optimization for a custom struct that wraps a reference type. It also tests whether you understand the runtime uniqueness check and the thread safety implications of CoW.

The full answer

A good answer hits four things in order. First, define Copy-on-Write as a strategy where multiple value-typed instances share a reference to a buffer until one mutates it, at which point a real copy is made. Second, explain that Swift collections like Array and Dictionary use a reference-counted buffer and on mutation call isKnownUniquelyReferenced to determine if the buffer has more than one owner. Third, describe the implementation steps for a custom struct: create a private final class to hold the payload, store that reference in the struct, provide reads directly through the reference, and in any mutating method first check isKnownUniquelyReferenced on the backing instance; if it returns false, create a new instance with copied data and assign it before modifying. Fourth, note that this preserves value semantics from the callers perspective while avoiding unnecessary allocations.

The mistakes people make

A common wrong answer is claiming that all structs in Swift automatically exhibit CoW behavior. In reality, only standard library collections and types you explicitly build do this. Another red flag is forgetting the uniqueness check and mutating the shared reference directly, which corrupts every other value that points to the same buffer. Some candidates also suggest using a struct instead of a class for the backing storage, which defeats the reference sharing mechanism entirely. Finally, mentioning manual retain counts or deep copy on every assignment shows a misunderstanding of the optimization goal.

What usually comes next

The interviewer may ask how CoW interacts with multithreading, specifically that isKnownUniquelyReferenced is only reliable when no other thread could be retaining the object, so you should discuss why mutation and uniqueness checks should happen on the same thread or within proper synchronization. They might also ask for the performance tradeoff, namely that the first mutation after sharing costs O(n) to copy, while subsequent reads and writes on a unique reference are O(1). Another follow-up is asking how to test CoW behavior, such as using withUnsafeMutablePointer or simply observing reference counts and allocation metrics.

A concrete example

Imagine a custom struct named Buffer that wraps an array of integers. Inside Buffer you define a final class Storage with a var elements property. The struct holds a private var storage property. A subscript reads storage elements directly. A mutating append method first checks if isKnownUniquelyReferenced returns false on storage; if false, it sets storage to Storage with elements copied from storage elements to detach from any shared reference, then appends. This ensures that var a equals buffer; var b equals buffer; b append one does not mutate a, and no copy occurs until b append is called.

Interview question

When implementing Copy-on-Write for a custom Swift struct, what must happen inside a mutating method before modifying the backing reference?

  • a.Change the backing storage to a struct so that the compiler automatically enforces value semantics without a uniqueness check
  • b.Verify isKnownUniquelyReferenced on the backing instance and clone it if the result is falseCorrect
  • c.Deep copy the backing buffer whenever the outer struct is assigned to prevent sharing from the start
  • d.Check isKnownUniquelyReferenced and clone the buffer only when the check returns true, because that indicates multiple owners
Why?

Before mutating, you must check isKnownUniquelyReferenced and clone when it returns false, indicating shared ownership. Answer A dangerously inverts the boolean logic, while C and D reflect common misconceptions that either defeat reference sharing or eliminate the optimization entirely.

Just read this? Test yourself on what you have been reading.

Read the original → developer.apple.com

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on swift — each one lists the topics its interview covers.

See open roles