Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI passing touch events from UIViewControllerRepresentable to View behind

I'm working on a project which uses a mixture of UIKit and SwiftUI. I currently have a ZStack which I hold my SwiftUI content in, I need to display a UIViewController over top of that content. So the last item in my ZStack is a UIViewControllerRepresentable. ie:

ZStack {
   ...
   SwiftUIContent
   ...
   MyUIViewControllerRepresentative() 
}

My overlaid UIViewControllerRepresentative is a container for other UIViewControllers. Those child view controllers don't always need to take up the full screen, so the UIViewControllerRepresentative has a transparent background so the user can interact with the SwiftUI content behind.

The problem I'm facing is that the UIViewControllerRepresentative blocks all touch events from reaching the SwiftUI content.

I've tried overriding the UIViewControllers views hit test like so:

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    // return nil if the touch event should propagate to the SwiftUI content
}

I've also event tried completely removing the touch events on the view controllers view with:

view.isUserInteractionEnabled = false

Even that doesn't work.

Any help would be really appreciated.

like image 887
Nick Russell Avatar asked Dec 01 '19 21:12

Nick Russell


2 Answers

SOLUTION:

I managed to come up with a solution that works.

Instead of putting the UIViewControllerRepresentable inside the ZStack, I created a custom ViewModifier which passes the content value into the UIViewControllerRepresentable. That content is then embedded within my UIViewController by wrapping it inside of a UIHostingController and adding it as a child view controller.

ZStack {
    ... SwiftUI content ...
}.modifier(MyUIViewControllerRepresentative)
like image 138
Nick Russell Avatar answered Sep 25 '22 03:09

Nick Russell


You could use allowsHitTesting() modifier on the UIViewControllerRepresentable.

As Paul Hudson states on his website: https://www.hackingwithswift.com/quick-start/swiftui/how-to-disable-taps-for-a-view-using-allowshittesting

"If hit testing is disallowed for a view, any taps automatically continue through the view on to whatever is behind."

ZStack {
   ...
   SwiftUIContent
   ...
   MyUIViewControllerRepresentative()
       .allowsHitTesting(false)
}
like image 25
Juan Carlos Gonzalez Avatar answered Sep 25 '22 03:09

Juan Carlos Gonzalez