Home > Blockchain >  Swift set default value referencing binding
Swift set default value referencing binding

Time:02-21

I'm probably not understanding the basics and confused, but I couldn't figure out the reason of things below. Ok, what I want to do is pass Int64 to sub view and show Toggles based on bits and set the bits back to parent view like this:

struct ContentView: View {
    @State var bits: Int64 = 5

    var body: some View {
        Form {
            Section {
                SectionView(title: "Section", withBits: $bits)
            } header: {
                Text("Toggle")
            }
        }
    }
}

struct SectionView: View {
    let title: String
    @Binding var bits: Int64

    @State private var first: Bool
    @State private var second: Bool
    @State private var third: Bool

    init(title: String, withBits: Binding<Int64>) {
        self.title = title
        self._bits = withBits
        self.first = self.bits & 1 == 1
        self.second = self.bits & 2 == 2
        self.third = self.bits & 4 == 4
    }

    var body: some View {
        VStack {
            HStack {
                Text(self.title)
            }
            HStack {
                Toggle("Toggle 1", isOn: self.$first)
                    .onChange(of: self.first) { newValue in
                        if newValue {
                            self.bits |= 1
                        }
                        else {
                            self.bits &= ~1
                        }
                    }
            }
            HStack {
                Toggle("Toggle 2", isOn: self.$second)
                    .onChange(of: self.second) { newValue in
                        if newValue {
                            self.bits |= 2
                        }
                        else {
                            self.bits &= ~2
                        }
                    }
            }
            HStack {
                Toggle("Toggle 3", isOn: self.$third)
                    .onChange(of: self.third) { newValue in
                        if newValue {
                            self.bits |= 4
                        }
                        else {
                            self.bits &= ~4
                        }
                    }
            }
        }
        .onChange(of: self.bits) { newValue in
            print("bits: \(bits)")
        }
    }
}

But it won't compile. Saying "'self' used before all stored properties are initialized" error.

So I set default values to all Bool vars like this:

    @State private var first: Bool = false
    @State private var second: Bool = false
    @State private var third: Bool = false

It compiles now but cannot overwrite them in int(), below lines are completely ignored.

        self.first = self.bits & 1 == 1
        self.second = self.bits & 2 == 2
        self.third = self.bits & 4 == 4

Moving above three lines to onAppear() worked. But still I want to know why they won't be overwritten in init() and cleanest way.

CodePudding user response:

Avoid using in your initialiser the variables being initialised, if you can. The Binding has no value in the beginning, that's why you need to wait for your View to appear.

Try replacing the initialisation for your 3 variables with the following code (using init() and not .onAppear()):

self.first = withBits.wrappedValue & 1 == 1      // Why using an always true condition? OK if this is just a placeholder
self.second = withBits.wrappedValue & 2 == 2
self.third = withBits.wrappedValue & 4 == 4
  • Related