SwiftUI 在 UIViewController 中调用委托
SwiftUI calling delegate in UIViewController
这是我第一次使用 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 中声明 facialView 时,我无法访问 configureForInstructionMode() 中的实例,或者它的值为 nil..
您只需将对 MyViewController
实例的引用传递给 MyUIView
(可能应该是 MyView
,因为它不是 UIView
的子类) 通过它的初始化器。您可以使用委托模式,也可以传递一个闭包,然后从闭包中调用委托方法。第二种方式更“迅捷”。
(我已将代码移至 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,我已经搜索过这个问题但没有找到任何有效的解决方案,所以我将不胜感激所有能得到的帮助。
我有一个 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 中声明 facialView 时,我无法访问 configureForInstructionMode() 中的实例,或者它的值为 nil..
您只需将对 MyViewController
实例的引用传递给 MyUIView
(可能应该是 MyView
,因为它不是 UIView
的子类) 通过它的初始化器。您可以使用委托模式,也可以传递一个闭包,然后从闭包中调用委托方法。第二种方式更“迅捷”。
(我已将代码移至 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")
}
}
}
}