How to maintain value semantics in structs having references properties?

Let's say I have a structure that stores some data in its internal class. But this is exactly the structure. And if this structure is copied in the code, how can I copy the object with all the data contained in this object, at the time of assign the structure to new variable?

class Storage {
    var item: String = ""
    func upload(item: String) { self.item = item }
    func download(key: String) -> String { item }
}

struct StackOnDisk {
    let storage: Storage
    init() {
        storage = Storage()
    }
    mutating func push(item: String) { storage.upload(item: item) }
    mutating func pop(key: String) -> String { storage.download(key: key) }
}

class Controller {
    func work() {
        var stackone = StackOnDisk()
        stackone.push(item: "Maya")
        var stacktwo = stackone // How to initialize new Storage at stacktwo instance at this moment?
        stacktwo.push(item: "Willy")
        let firstitem = stackone.pop(key: "key")
        print(firstitem)
    }
}

func test() {
    Controller().work() // prints Willy, it is no good, it must prints Maya
}

You generally don't want to make a copy at the time of assignment. Try instead to use Copy-on-Write (CoW) semantic. Check if your StackOnDisk instance is the only one holding onto Storage during the mutation using isKnownUniquelyReferenced, and if so, mutate in-place. Otherwise, make a copy:

struct StachOnDisk {
  ...
  mutating func push(item: String) {
    if !isKnownUniquelyReferenced(storage) {
      // We're sharing `storage`, make a copy
      storage = Storage(item: storage.item)
    }

    storage.upload(item: item)
  }
}
9 Likes

I don't think this is possible anyway. Unlike C++, Swift doesn't have a copy constructor. CoW is pretty much the only option.