1
\$\begingroup\$

This is my current View hierarchy:

ParentView:View {
     ChildView1: UIViewRepresentable
     ChildView2: View
}

In ChildView2 I have a button who's action I want to pass to ChildView1. That action is a @Binding on ChildView2, a @State in ParentView where it also is declared, and also a @Binding on ChildView1, where the action takes place.

This is my code:

typealias OnClickHandler = (() -> Void)

struct ParentView: View {
    @State var onClick: OnClickHandler = { }

    var body: some View {
        ZStack {
             VStack {
                ChildView1(onClick: $onClick)
            }

            VStack(alignment:.trailing) {
                Spacer()
                HStack {
                    Spacer()
                    ChildView2(onClick: $onClick)
                }.padding(EdgeInsets(top: 0, leading: 0, bottom: 30, trailing: 5))
            }
        }
    }
}

struct ChildView2: View {
    @Binding var onClick: OnClickHandler

    var body: some View {
        VStack {
            Button(action: onClick) {
                Image("SexyImage")
            }
    }
}

struct ChildView1: UIViewRepresentable {
    @Binding var onClick: OnClickHandler

    func makeUIView(context: Context) -> UIView {
        let view = UIView()

        //"Modifying state during view update, this will cause undefined behavior"
        //if I don't send it to a background thread.
        DispatchQueue.global(qos: .background).async {
            self.onClick = self.foo
        }

        return view
    }

    public func foo() {
        print("bar")
    }

    internal func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
}

After a couple of days of trial and error, this is the best (and only) solution I found. I use a background thread, otherwise I get a warning for modifying the state during UI update.

I'm curious if there is a better solution.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.