5

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,

5
  • 1
    Just remove this init(hasSilence: Bool) initialiser and create ResultViewSilence in parent with both arguments according to type. Commented Oct 25, 2020 at 4:34
  • Sure, the problem is that when I do that by using '''ResultViewSilence(hasSilence: isSilence, isDimissView: $isDismissView)''', it forces me to initialize it in the initializer of the parent, and it gives me another error: ''''self' used in property access '$isDismissView' before all stored properties are initialized''' Commented Oct 25, 2020 at 12:39
  • I think the proper way should be directly to avoid initializing the Binding in the children init(), and according to the docs it should be working but not sure why is not working Commented Oct 25, 2020 at 12:42
  • it gives me another error - would add to question how do you do that, I assume the problem to be solved is there? Commented Oct 25, 2020 at 13:00
  • By using parameters for initialization in the children's view, that forces me to call it from the parent with the parameters. The consequence is that it forces me to initialize the variable in the parent itself, which it seems to be impossible by using ResultViewSilence(hasSilence: isSilence, isDimissView: $isDismissView) as it $isDismissView - self is used before all stored properties are initialized. Commented Oct 26, 2020 at 12:19

1 Answer 1

14
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()
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.