Mark Bridges
Mark Bridges

Reputation: 8448

Pass touches through a UIViewController

I have a view controller that I overlay on top of another view controller. I just need the top view controller so I can overlay a temporary pop up notification, and having an overlayed VC allows me to present this over a UITableViewController as you can't add subviews to tableview controllers directly.

Is it possible to interact with the bottom view controller while it has another view controller covering it. If this were a view or a window you would achieve this by setting user interaction to false or using hitTest but neither of these approaches works for a view controller.

Upvotes: 14

Views: 9710

Answers (1)

Tiran Ut
Tiran Ut

Reputation: 1046

Create subclass like this

class TouchDelegatingView: UIView {
    weak var touchDelegate: UIView? = nil


    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        guard let view = super.hitTest(point, with: event) else {
            return nil
        }

        guard view === self, let point = touchDelegate?.convert(point, from: self) else {
            return view
        }

        return touchDelegate?.hitTest(point, with: event)
    }
}

Then in your ViewController set view class (you can do it directly in xib, or inside loadView() method)

And add

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        if let delegatingView = view as? TouchDelegatingView {
            delegatingView.touchDelegate = presentingViewController?.view
        }
    }
}

Also you can use this mechanism to delegate touches to any other view, no matter if it

Upvotes: 21

Related Questions