SwiftUI 在 UIViewController 中调用委托
Posted
技术标签:
【中文标题】SwiftUI 在 UIViewController 中调用委托【英文标题】:SwiftUI calling delegate in UIViewController 【发布时间】:2021-08-24 22:32:18 【问题描述】:这是我第一次使用 SwiftUI,我已经搜索过这个问题,但没有找到任何可行的解决方案,所以我将不胜感激。
我有一个 UIViewController,我在其中通过 UIHostingController 呈现一个 SwiftUI 视图。我想要实现的是,当我在 SwiftUI 视图中按下按钮时,该操作将触发 UIViewController 中的委托,或者,触发 UIViewController 中的一个函数,然后从该函数触发委托。
class MyViewController: UIViewController
public var delegate: MyViewControllerDelegate?
let facialView = UIHostingController(rootView: FacialTutorial())
override func viewWillAppear(_ animated: Bool)
addChild(facialView)
view.addSubview(facialView.view)
setupConstraints()
extension MyViewController
@objc private func buttonPressed()
delegate?.buttonPressed()
在我的 SwiftUI 视图中 FacialTutorial
struct FacialTutorial: View
var body: some View
VStack()
Button
// I want to call delegate?.buttonPressed() action here
label:
Text("Press button")
编辑
好吧,说得更清楚些,我的 ViewController 在很多情况下对页面进行了不同的配置。所以在实践中,我不会从 viewWillAppear 启动 SwiftUI 视图。相反,我就是这样做的
public var delegate: MyViewControllerDelegate?
let facialView = UIHostingController(rootView: FacialTutorial())
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
addChild(facialView)
configureSubviews()
private func configureForInstructionMode()
view.addSubview(facialUIView.view)
setupConstraints()
我必须采用这种方式,因为我需要根据要配置的模式来不同地配置视图。当我在 viewDidLoad 或 viewWillAppear 中声明 faceView 时,我无法访问 configureForInstructionMode() 中的实例,或者它的值为 nil..
【问题讨论】:
这能回答你的问题吗? SwiftUI - Button - How to pass a function request to parent 【参考方案1】:您只需要通过其初始化程序将对您的MyViewController
实例的引用传递给MyUIView
(可能应该是MyView
,因为它不是UIView
的子类)。您可以使用委托模式,也可以传递一个闭包,然后从闭包中调用委托方法。第二种方式更“Swifty”。
(我已将代码移至viewDidLoad
,因为如果您在viewWillAppear
中有它,如果视图控制器出现、消失并再次出现,则视图可能会被多次添加)
class MyViewController: UIViewController
public var delegate: MyViewControllerDelegate?
weak var myView: UIHostingController<MyUIView>!
override func viewDidLoad()
super.viewDidLoad()
let myView = UIHostingController(rootView: MyUIView(buttonHandler: [weak self] in
self?.delegate?.buttonPressed()
))
self.myView = myView
view.addSubview(myView.view)
setupConstraints()
然后,在您的 SwiftUI 视图中,您可以声明一个属性来保存闭包并在您的按钮中调用该闭包
struct MyUIView: View
var buttonHandler: (()->Void)?
var body: some View
VStack()
Button
buttonHandler?()
label:
Text("Press button")
【讨论】:
实际上它现在工作了!谢谢您的帮助。顺便问一下,你知道我在启动时如何将一些参数传递给 SwiftUI 视图吗?这样我就可以传递我想要配置的模式,然后在我的 SwiftUI 中我可以针对特定模式调整视图? 和我传递闭包时一样——在MyUIView
中声明一个属性,然后通过初始化程序传递值。
好的,我做到了,它也有效。但是我注意到我只想在某些模式下显示 SwiftUI 视图,而在其他模式下不启动 SwiftUI 视图而只使用常规 ViewController。这就是为什么我将 SwiftUI 的启动移到特定函数中的原因,这样当特定模式为 true 时,才会启动 SwiftUI 视图。你知道怎么做吗?
您在加载视图之前设置视图控制器的相关属性,然后您可以在viewDidLoad
中测试这些属性。确切的方式取决于您如何访问此视图控制器 - segue,只是显示或呈现它。在viewWillAppear
中将视图设置为hidden
也可能是一个选项。以上是关于SwiftUI 在 UIViewController 中调用委托的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI - 如何在 SwiftUI 中弹出到特定视图?
SwiftUI - SwiftUI 中是不是有等效的 popViewController?