HostingPassthrough icon indicating copy to clipboard operation
HostingPassthrough copied to clipboard

Allow working with Interface Builder

Open alobaili opened this issue 2 years ago • 2 comments

Thanks for this brilliant solution.

It would be awesome if it can also work with view controllers that use Interface Builder. I tested this library on a view controller that have some IB outlets from an XIB and once I make the view controller a subclass of HostingParentController, all outlets become nil.

alobaili avatar Jun 06 '23 14:06 alobaili

@alobaili this code works for me with storyboard. Please test thoroughly and give feedback. (I also changed func viewWillLayoutSubviews() to open.)

open class HostingParentController: UIViewController {
    
    public var makeBackgroundsClear = true
    
    /// If the touches land on the base view of the HostingParentController, they will be forwarded to this view if it is not nil.
    public var forwardBaseTouchesTo: UIView?
    
    /// If the touches land on the bottom of a SwiftUI scroll container (*not* the content), pass through these touches to the UIKit layer underneath.
    public var ignoreTouchesOnSwiftUIScrollView = false
    
    override open func loadView() {
        if isLoadedFromStoryboard {
            super.loadView()  // Load the view from the storyboard
        } else {
            let capturer = HostingParentView()
            view = capturer
        }
    }
    
    private var isLoadedFromStoryboard: Bool {
        return storyboard != nil
    }
    
    private func wrapOriginalViewWithHostingParentView() {
        let originalView = self.view!
        
        let capturer = HostingParentView(frame: originalView.frame)
        self.view = capturer
        
        capturer.addSubview(originalView)
        originalView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            originalView.topAnchor.constraint(equalTo: capturer.topAnchor),
            originalView.bottomAnchor.constraint(equalTo: capturer.bottomAnchor),
            originalView.leadingAnchor.constraint(equalTo: capturer.leadingAnchor),
            originalView.trailingAnchor.constraint(equalTo: capturer.trailingAnchor)
        ])
    }

    open override func viewDidLoad() {
        super.viewDidLoad()

        // Only wrap the view if loaded from a storyboard
        if isLoadedFromStoryboard {
            wrapOriginalViewWithHostingParentView()
        }
    }
    
    open override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        
        if let capturer = view as? HostingParentView {
            capturer.makeBackgroundsClear = makeBackgroundsClear
            capturer.forwardBaseTouchesTo = forwardBaseTouchesTo
            capturer.ignoreTouchesOnSwiftUIScrollView = ignoreTouchesOnSwiftUIScrollView
        }
    }
}

GerdC avatar Aug 08 '23 20:08 GerdC

Using the code above intensely for a few days now and it is absolutely stable for me.

GerdC avatar Aug 15 '23 08:08 GerdC