【问题标题】:How to dismiss swiftUI from Viewcontroller?如何从 Viewcontroller 中关闭 swiftUI?
【发布时间】:2019-12-15 00:04:34
【问题描述】:

在我的视图控制器中我有这个功能

...{
let vc = UIHostingController(rootView: SwiftUIView())
        present(vc, animated: true, completion: nil)
}

其中呈现以下 SwiftUIView。

Q 如何在按下 CustomButton 时关闭 SwiftUIView?

struct SwiftUIView : View {
     var body: some View {
       CustomButton()
     }   
}

struct CustomButton: View {

    var body: some View {
        Button(action: {
            self.buttonAction()
        }) {
            Text(buttonTitle)
        }
    }

    func buttonAction() {
        //dismiss the SwiftUIView when this button pressed
    }       
}

【问题讨论】:

  • 你看过这个问题吗? stackoverflow.com/questions/56819063/…
  • 您必须定义一个@State 并将其传递给相关的controlling 控制的视图。
  • 以下。如果你还没有尝试过——你可以通过向下拖动控制器来关闭它——但是......我当然想要并且正在寻找一种解决方案来关闭按钮按下。 :)
  • @ovatsug25 是的,我需要按下按钮,因为在拖动关闭时不会触发 .onDisappear 回调,因此需要预先定义的操作来执行某些功能。

标签: swiftui uihostingcontroller


【解决方案1】:
struct CustomButton: View {

    var body: some View {
        Button(action: {
            self.buttonAction()
        }) {
            Text(buttonTitle)
        }
    }

    func buttonAction() {
        if let topController = UIApplication.topViewController() {
            topController.dismiss(animated: true)
        }
    }       
}

extension UIApplication {
    class func topViewController(controller: UIViewController? = UIApplication.shared.windows.first { $0.isKeyWindow }?.rootViewController) -> UIViewController? {
        if let navigationController = controller as? UINavigationController {
            return topViewController(controller: navigationController.visibleViewController)
        }
        if let tabController = controller as? UITabBarController {
            if let selected = tabController.selectedViewController {
                return topViewController(controller: selected)
            }
        }
        if let presented = controller?.presentedViewController {
            return topViewController(controller: presented)
        }
        return controller
    }
}

或者如果这不起作用,因为您在顶部有不同的视图控制器,或者如果您需要使用视图生命周期事件(onDisappear 和 onAppear 不适用于 UIHostingController)。 你可以改用:

final class SwiftUIViewController: UIHostingController<CustomButton> {
    required init?(coder: NSCoder) {
        super.init(coder: coder, rootView: CustomButton())
        rootView.dismiss = dismiss
    }
    
    init() {
        super.init(rootView: CustomButton())
        rootView.dismiss = dismiss
    }
    
    func dismiss() {
        dismiss(animated: true, completion: nil)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        rootView.prepareExit()
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        rootView.doExit()
    }
}

struct CustomButton: View {
    var dismiss: (() -> Void)?
    
    var body: some View {
        Button(action: dismiss! ) {
            Text("Dismiss")
        }
    }
    func prepareExit() {
        // code to execute on viewWillDisappear
    }
    func doExit() {
        // code to execute on viewDidDisappear
    }
}

【讨论】:

  • 对我来说,这个答案给出的错误如下:Type 'UIApplication' has no member 'topViewController'
  • @Doug 抱歉,我忘了我正在使用扩展,它会关闭顶部的 ViewController
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 2014-08-31
  • 2018-11-09
  • 2011-07-21
  • 1970-01-01
  • 2017-12-19
相关资源
最近更新 更多