I\'m trying to find a way to trigger an action that will call a function in my UIView when a button gets tapped inside swiftUI.
M Reza's solution works for simple situations, however if your parent SwiftUI view has state changes, every time when it refreshes, it will cause your UIViewRepresentable to create new instance of UIView because of this: let someView = SomeView() // add this instance. Therefore someView.foo() is calling the action on the previous instance of SomeView you created, which is already outdated upon refreshing, so you might not see any updates of your UIViewRepresentable appear on your parent view.
See: https://medium.com/zendesk-engineering/swiftui-uiview-a-simple-mistake-b794bd8c5678
A better practice would be to avoid creating and referencing that instance of UIView when calling its function.
My adaption to M Reza's solution would be calling the function indirectly through parent view's state change, which triggers updateUIView :
var body: some View {
@State var buttonPressed: Bool = false
VStack(alignment: .center, spacing: 24) {
//pass in the @State variable which triggers actions in updateUIVIew
SomeViewRepresentable(buttonPressed: $buttonPressed)
.background(Color.gray)
HStack {
Button(action: {
buttonPressed = true
}) {
Text("Tap Here")
}
}
}
}
struct SomeViewRepresentable: UIViewRepresentable {
@Binding var buttonPressed: Bool
func makeUIView(context: Context) -> SomeView {
return SomeView()
}
//called every time buttonPressed is updated
func updateUIView(_ uiView: SomeView, context: Context) {
if buttonPressed {
//called on that instance of SomeView that you see in the parent view
uiView.foo()
buttonPressed = false
}
}
}