jmrueda
jmrueda

Reputation: 1428

Return from initializer without initializing all stored properties - SwiftUI Binding error

I have a couple of cascading modals that need to be refreshed depending on some background processes. In order to achieve this, I have created a struct where I hold all the logic for the UI and I am calling a couple of SwiftUI views with UIHostingController.init(rootView: views).

The challenge comes when I would like to dismiss the view by clicking a button from the child view. I am trying to use @State and @Binding but binding is forcing me to init the variable inside the child view.

Here is the code for the child:

struct ResultViewSilence: View {

@Binding var isDismissView: Bool
var hasSilence: Bool
let photolibrary = PhotoLibrary()

init(hasSilence: Bool) {
    self.hasSilence = hasSilence
    <--- here is where is asking to initialize isDismissView, but it should not be needed
}

I was able to init isDismissView, by doing this...

init(hasSilence: Bool, isDismissView: Binding<Bool>?) {
    ...
    self._isDismissView = isDismissView!

but if I do that then it would break in the parent as I cannot pass the @State as a parameter in the UIHostingController and it would be required.

The error I would get if I do this is:

"Accessing State's value outside of being installed on a View. This will result in a constant Binding of the initial value and will not update."

I am also checking the @State variable and is not changing even if the button is triggered.

Cheers,

Upvotes: 5

Views: 6116

Answers (1)

lorem ipsum
lorem ipsum

Reputation: 29464

import SwiftUI

struct ResultViewSilence: View {

    ///@State needs to be initialized here because it CAN store values
    ///https://developer.apple.com/documentation/swiftui/state
    @State var isDismissView1: Bool = false
    
    ///@Binding creates a 2 way connection does NOT store values needs a parent that stores values
    ///https://developer.apple.com/documentation/swiftui/binding
    @Binding var isDismissView2: Bool
    
    var hasSilence: Bool
    
    //let photolibrary = PhotoLibrary() //No code provided

    init(hasSilence: Bool, isDismissView2: Binding<Bool> ) {
        self.hasSilence = hasSilence
        self._isDismissView2 = isDismissView2
    }
    var body: some View {
        VStack{
            Text("isDismissView1 = " + isDismissView1.description)
            Text("isDismissView2 = " + isDismissView2.description)
        }
    }
}
struct ParentResultViewSilence: View {
    //Parent that can store values
    @State var isDismissView2: Bool = true
    var body: some View {
        ResultViewSilence(hasSilence: false, isDismissView2: $isDismissView2)
    }
}
struct ResultViewSilence_Previews: PreviewProvider {
    static var previews: some View {
        //ResultViewSilence(hasSilence: false, isDismissView2: .constant(true))
        ParentResultViewSilence()
    }
}

Upvotes: 14

Related Questions