Warm tip: This article is reproduced from serverfault.com, please click

Delegate for SwiftUI View from Hosting View Controller

发布于 2020-11-30 15:19:19

I add UIHostingViewController to my Storyboard and make class for this. Load mySwiftUIView in controller init. Everything works good.

But i want to make hosting controller like delegate for mySwiftUIView because I want to handle button pressing in view.

required init?(coder: NSCoder) {
    var mySwiftView = MySwiftUIView()
    mySwiftView.delegate = self //self used before super.init call
    super.init(coder: coder,rootView: mySwiftView)
}

Id doesn't work because I pass view before hosting controller fully init. Swift shows message "self used before super.init call"

If I will use usual UIViewController and put HostingController inside - it is works. But this is not suitable for me because it calls problem with sizes and navigation.

How can I do it with separate UIHostingController. Thanks

Full code

import UIKit
import SwiftUI

protocol MySwiftUIViewDelegate{
    func buttonPressed()
}

struct MySwiftUIView: View {
    var delegate: MySwiftUIViewDelegate?
    
    var body: some View {
        Button(action: {
            delegate?.buttonPressed()
        }) {
            Text("My button")
        }
    }
}

class MyHostingViewController: UIHostingController<MySwiftUIView>, MySwiftUIViewDelegate {
        
required init?(coder: NSCoder) {
    var mySwiftView = MySwiftUIView()
    //mySwiftView.delegate = self //self used before super.init call
    super.init(coder: coder,rootView: mySwiftView)
}

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

func buttonPressed() {
    performSegue(withIdentifier: "GoToOtherScreenSegue", sender: self)
}
}
Questioner
Ivan
Viewed
0
EDUsta 2020-11-30 23:35:06

Since MyHostingViewController knows that its rootView is MySwiftUIView, you could assign the view controller as the delegate afterwards:

required init?(coder: NSCoder) {
    var mySwiftView = MySwiftUIView()
    super.init(coder: coder, rootView: mySwiftView)
    rootView.delegate = self
}