如何让UIHostingController内嵌SwiftUI按钮触发UIViewController的delegate
解决方案
核心实现逻辑是给SwiftUI视图增加回调闭包,接收按钮点击事件后通知上层UIViewController处理,具体修改步骤如下:
步骤1:修改FacialTutorial视图
新增回调闭包属性,点击按钮时触发该闭包:
struct FacialTutorial: View { // 新增无参数无返回值的闭包,用于对外通知点击事件 var onButtonTap: () -> Void var body: some View { VStack { Button { // 按钮点击时执行回调 onButtonTap() } label: { Text("Press button") } } } }
步骤2:修改MyViewController实现
将facialView改为懒加载属性,初始化SwiftUI视图时传入回调闭包,闭包内调用自身的buttonPressed方法即可触发delegate:
class MyViewController: UIViewController { public var delegate: MyViewControllerDelegate? // 改为懒加载属性,保证初始化时self已经完成初始化,可以正常引用 lazy var facialView = UIHostingController(rootView: FacialTutorial(onButtonTap: { [weak self] in // 避免循环引用,使用weak修饰self self?.buttonPressed() })) override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) addChild(facialView) view.addSubview(facialView.view) setupConstraints() } private func setupConstraints() { // 保留原有的约束逻辑即可 } } extension MyViewController { @objc private func buttonPressed() { delegate?.buttonPressed() } }
适配差异化配置需求
该方案完全适配你提到的多场景配置逻辑:
- facialView改为懒加载属性后仍然是类的全局成员,你可以在
configureForInstructionMode等任意实例方法中正常访问,不会出现nil的问题 - 懒加载属性只会在第一次被访问时完成初始化,不会影响你不同模式下的差异化配置逻辑
- 闭包中添加
[weak self]修饰符,不会出现循环引用问题
内容的提问来源于stack exchange,提问作者Crystalii
相关产品推荐
相关产品推荐

