如何从 SwiftUI 按钮调用用 UIKit/UIController/Storyboard 编写的函数

How do I call a function written in UIKit/UIController/Storyboard from SwiftUI button

我是一个 SwiftUI 新手,正在努力为我现有的 UIKit/Storyboard 代码添加 SwiftUI 功能。我想从 SwiftUI 按钮调用 UIKit 函数。非常感谢您的帮助。这是针对此讨论简化的相关代码。 在下面的代码中,我想从 SwiftUI...

中的 If 语句调用函数 startAction() 和 stopAction()
                    if (startStop_flag) {

                        //******** call StartAction()

                    } else {

                        //******* call StopAction()

                    }

下面是完整的代码。 一些上下文:当应用程序是 运行 时,屏幕的下半部分将显示“UIkit Storyboard View”并显示按钮“Open Swift Container View”。当用户单击此按钮时,SwiftUI 容器视图将打开。该视图将显示“This is a swiftUI view”并显示一个按钮“Start/Stop”。当用户单击此按钮时,需要调用 StartAction() 或 StopAction()。这两个函数驻留在UIViewController中。我希望我清楚问题和要求。

ViewController.swift 

class ViewController: UIViewController {
    @IBOutlet weak var nativeView: UIView!
    @IBOutlet weak var nativeView_Label: UILabel!
    @IBOutlet weak var nativeView_openSwiftViewBtn: UIButton!
    @IBOutlet weak var containerView_forSwiftUI: UIView!



    
    @IBSegueAction func embedSwiftUIView(_ coder: NSCoder) -> UIViewController? {
        return UIHostingController(coder: coder, rootView: SwiftUIView2(text: "Container View"))
    }
    
    var toggleOpenCloseContainerView : Bool = false
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        
        containerView_forSwiftUI.isHidden = true
    }

    @IBAction func openContainerView_touchInside(_ sender: Any) {
        
        if (toggleOpenCloseContainerView) {
            containerView_forSwiftUI.isHidden = false
            toggleOpenCloseContainerView = false
            nativeView_openSwiftViewBtn.setTitle("Close Swift Container View", for: .normal)
        } else {
            containerView_forSwiftUI.isHidden = true
            toggleOpenCloseContainerView = true
            nativeView_openSwiftViewBtn.setTitle("Open Swift Container View", for: .normal)
        }
        
    }
    
    
    // These two functions need to be called from the SwiftUI's button.
    
    func startAction() {
        
        print("Start Action called from SwiftUI's button")
    }
    
    func stopAction() {
        
        print("Stop Action called from SwiftUI's button")
    }
    
}

swiftUI 函数在这个文件中


struct SwiftUIView2: View {
    
    var text: String
    @State var startStop_flag: Bool = true
    
    var body: some View {
        VStack {
            Text(text)
            HStack {
                Image(systemName: "smiley")
                Text("This is a SwiftUI View")
                Spacer()
                
                Button("\(startStop_flag ? "Start": "Stop")") {
                    startStop_flag = !startStop_flag
                    
                    if (startStop_flag) {
                        
                        //******** call StartAction()
                        
                    } else {
                        
                        //******* call StopAction()
                        
                    }
                    
                }   .padding()
                    .background(Color.red)
                    .cornerRadius(40)
                    .foregroundColor(.white)
                    .padding(5)
                    .overlay(
                        RoundedRectangle(cornerRadius: 40)
                            .stroke(Color.red, lineWidth: 1)
                    )
            }
        }
        .font(.largeTitle)
        .background(Color.blue)
        
    }
    
}

struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        SwiftUIView2(text: "Sample Text")
    }
}

您可以为此使用 closures。首先,在您的 SwiftUI 视图中定义并调用它们。

struct SwiftUIView2: View {
    
    var text: String
    var startAction: (() -> Void) /// define closure 1
    var stopAction: (() -> Void) /// define closure 2
    
    ...
    ...
    
    Button("\(startStop_flag ? "Start": "Stop")") {
        startStop_flag = !startStop_flag
        
        if (startStop_flag) {
            //******** call StartAction()
            startAction()
        } else {
            //******* call StopAction()
            stopAction()
        }
    }
}

然后,只需在 ViewController.swift.

中分配闭包的内容
@IBSegueAction func embedSwiftUIView(_ coder: NSCoder) -> UIViewController? {
    return UIHostingController(
        coder: coder,
        rootView: SwiftUIView2(
            text: "Container View",
            startAction: { [weak self] in
                self?.startAction()
            },
            stopAction: { [weak self] in
                self?.stopAction()
            }
        )
    )
}