6
votes

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.

2
I have also tried wrapping my view controller in UIViewRepresentable and exposing the just the view. Even with this, setting the view isUserInteractionEnabled to false didn't work.Nick Russell

2 Answers

4
votes

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)
1
votes

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)
}