Igor
Igor

Reputation: 109

How keep a copy of original binding value

I have a view that gets a binding Int from parent, modifies it and if Save button is tapped it saves, otherwise returns to initial value. So I want to keep a copy of original binding value.

I've tried lots of options, the best possible might seem to be the one below but copy is changing if I change amount 😫

Any ideas?

@Binding var amount: Int
var copy: Int { $amount.value }

Upvotes: 3

Views: 1697

Answers (1)

kontiki
kontiki

Reputation: 40489

The following code will let you persist your default value across view updates.

Nota that views may be recreated multiple times, and the only way to guarantee that a variable value persists across view regenerations, is by using either a @State variable, or a binding to something external. One option could be to pass two parameters to the view initialiser, one with the binding and another with the default value. Because your are passing the default value as a parameter, you always have it available.

However, we can improve it even better, and make it so that the initialiser keeps a copy of the initial value, in case you want to reset your binding. For that, we need a @State variable. @State variables cannot be modified outside the view body, but you can initialise them. For that you set the backing store (_varName) as shown in code:

Beta 4 changed the way property wrappers are implemented, code updated.

import SwiftUI

struct ContentView: View {
    @State private var amount: Double = 10
    var body: some View {
        VStack {
            Text("AMOUNT = \(amount)")
            SubView(amount: $amount)
        }
    }
}

struct SubView: View {
    @Binding var amount: Double
    @State var defaultValue: Double

    init(amount: Binding<Double>) {
        // Beta 3:
        // self.$amount = amount
        // self.$$defaultValue = State(initialValue: amount.value)

        // Beta 4:
        self._amount = amount
        self._defaultValue = State(initialValue: amount.value)
    }

    var body: some View {
        VStack {
            Slider(value: $amount, from: 1, through: 100, by: 10)

            HStack(spacing: 20) {
                Button(action: {
                    print("default = \(self.defaultValue)")
                    self.amount = self.defaultValue
                }, label: {
                    Text("Reset")
                })

                Button(action: {
                    print("save \(self.amount)")
                }, label: {
                    Text("Save")
                })
            }
        }
    }
}

Upvotes: 6

Related Questions