从托管视图控制器委托 SwiftUI 视图

Delegate for SwiftUI View from Hosting View Controller

我将 UIHostingViewController 添加到我的 Storyboard 并为此制作了 class。 在控制器初始化中加载 mySwiftUIView。一切正常。

但我想为我的SwiftUIView 创建像委托一样的托管控制器,因为我想处理视图中的按钮按下。

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

Id 不起作用,因为我在托管控制器完全初始化之前通过了视图。 Swift 显示消息“在 super.init 调用之前已使用”

如果我将使用通常的 UIViewController 并将 HostingController 放入其中 - 它是有效的。但这不适合我,因为它会调用尺寸和导航问题。

如何使用单独的 UIHostingController 来实现。谢谢

完整代码

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

由于 MyHostingViewController 知道它的 rootViewMySwiftUIView,您可以随后将视图控制器指定为委托:

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

您可以将委托包装成 class

import UIKit
import SwiftUI

protocol MySwiftUIViewDelegate{
    func buttonPressed()
}

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

extension MySwiftUIView {
    final class Configuration {
        unowned var delegate: MySwiftUIViewDelegate?
    }
}

class MyHostingViewController: UIHostingController<MySwiftUIView>, MySwiftUIViewDelegate {
        
    required init?(coder: NSCoder) {
        let configuration = MySwiftUIView.Configuration()
        let mySwiftView = MySwiftUIView(configuration: configuration)
        super.init(coder: coder,rootView: mySwiftView)
        configuration.delegate = self
    }

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

    func buttonPressed() {
        performSegue(withIdentifier: "GoToOtherScreenSegue", sender: self)
    }
}