I am trying to use a custom Copy-on-write type with SwiftUI. I have found that it takes the expensive path every time in the below code. Any thoughts about how I can avoid the copy and deinit for every drag event? Thanks for any insights or hints you might have.
Code Block swift struct CowType { init() { self.detail = Detail(values: []) } private var detail: Detail var values: [Int] { detail.values } mutating func appendValue(_ value: Int) { if !isKnownUniquelyReferenced(&detail) { print("performing expensive copy") detail = Detail(values: values) } detail.values.append(value) } private final class Detail { init(values: [Int]) { self.values = values } deinit { print("calling deinit") } var values: [Int] } } struct ContentView: View { @State var state = CowType() var body: some View { Text("Hello, world! \(state.values.count)") .padding() .gesture(DragGesture().onChanged { _ in state.appendValue(Int.random(in: 1...100)) }) } }
As @OOPer indicated, using an object is a way around the problem:
I needed to use this to avoid the expensive copies.
Interestingly, @Published runs into the same problem as @State, making a copy at every iteration. e.g.,
This makes cow make a copy every time it is mutated.
I needed to use this to avoid the expensive copies.
Code Block swift final class Container: ObservableObject { private var cow = CowType() var values: [Int] { cow.values } func append(_ value: Int) { objectWillChange.send() cow.append(value) } }
Interestingly, @Published runs into the same problem as @State, making a copy at every iteration. e.g.,
Code Block swift final class Container: ObservableObject { @Published var cow = CowType() }
This makes cow make a copy every time it is mutated.