【问题标题】:How do I call a function written in UIKit/UIController/Storyboard from SwiftUI button如何从 SwiftUI 按钮调用用 UIKit/UIController/Storyboard 编写的函数
【发布时间】:2021-09-25 14:09:15
【问题描述】:

我是一名 SwiftUI 新手,正在努力将 SwiftUI 功能添加到我现有的 UIKit/Storyboard 代码中。我想从 SwiftUI 按钮调用 UIKit 函数。非常感谢您的帮助。这是本次讨论简化的相关代码。 从下面的代码中,我想从 SwiftUI 的 If 语句中调用函数 startAction() 和 stopAction()...

                    if (startStop_flag) {

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

                    } else {

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

                    }

下面的整个代码。 一些上下文:当应用程序运行时,屏幕的下半部分将显示“UIkit Storyboard View”并显示“Open Swift Container View”按钮。当用户单击此按钮时,将打开 SwiftUI 容器视图。此视图将显示“这是一个 swiftUI 视图”并显示一个按钮“开始/停止”。当用户单击此按钮时,需要调用 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")
    }
}

【问题讨论】:

    标签: ios swift swiftui uikit


    【解决方案1】:

    您可以为此使用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()
                }
            )
        )
    }
    

    【讨论】:

    • 感谢 Aheze 的快速回复。我正在尝试采纳您的建议,但有点坚持对 preview() 函数的更改。有什么建议吗?
    • 修改了预览,它起作用了。非常感谢。
    猜你喜欢
    • 2022-01-22
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-08
    相关资源
    最近更新 更多