如何在主ViewController中访问自定义View的按钮点击事件?
实现主ViewController访问自定义View按钮点击事件的几种方式
我来给你捋捋几种靠谱的实现方式,都是iOS开发里常用的套路,你可以根据自己的场景选:
方式一:代理模式(最符合iOS设计规范,适合复杂交互场景)
这种方式能很好地解耦自定义View和主ViewController,适合后续可能扩展更多交互的场景。
步骤1:修改自定义View代码,添加代理协议和代理属性
import UIKit // 定义代理协议,声明按钮点击的回调方法 protocol TextCustomisationVCDelegate: AnyObject { func textCustomisationVCButtonTapped(_ customView: TextCustomisationVC) } class TextCustomisationVC: UIView { @IBOutlet var contentView: UIView! @IBOutlet weak var customButton: UIButton! // 关联XIB里的按钮 // 代理属性,用weak避免循环引用 weak var delegate: TextCustomisationVCDelegate? override init(frame: CGRect) { super.init(frame: frame) commonInit() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) commonInit() } private func commonInit() { // 加载XIB到当前View Bundle.main.loadNibNamed("TextCustomisationVC", owner: self, options: nil) contentView.frame = bounds addSubview(contentView) // 给按钮绑定点击事件(如果XIB里没关联IBAction的话) customButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) } // 按钮点击的内部处理,调用代理方法通知外部 @objc private func buttonTapped() { delegate?.textCustomisationVCButtonTapped(self) } // 如果你的XIB里已经给按钮关联了IBAction,就替换成下面这段: // @IBAction func buttonTapped(_ sender: UIButton) { // delegate?.textCustomisationVCButtonTapped(self) // } }
步骤2:在主ViewController里实现代理
class MainViewController: UIViewController, TextCustomisationVCDelegate { @IBOutlet weak var customView: TextCustomisationVC! // 已经关联的自定义View override func viewDidLoad() { super.viewDidLoad() // 设置自定义View的代理为当前VC customView.delegate = self } // 实现代理方法,处理按钮点击逻辑 func textCustomisationVCButtonTapped(_ customView: TextCustomisationVC) { print("自定义View的按钮被点击啦!") // 这里可以加你需要的逻辑,比如弹出提示、跳转页面等 showTapAlert() } private func showTapAlert() { let alert = UIAlertController(title: "提示", message: "按钮点击成功", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) } }
方式二:闭包回调(简洁直观,适合简单交互场景)
如果你的交互逻辑比较简单,闭包会比代理更简洁,代码量更少。
步骤1:修改自定义View代码,添加闭包属性
import UIKit class TextCustomisationVC: UIView { @IBOutlet var contentView: UIView! @IBOutlet weak var customButton: UIButton! // 定义闭包属性,可选类型,避免未赋值时崩溃 var onButtonTapped: (() -> Void)? override init(frame: CGRect) { super.init(frame: frame) commonInit() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) commonInit() } private func commonInit() { Bundle.main.loadNibNamed("TextCustomisationVC", owner: self, options: nil) contentView.frame = bounds addSubview(contentView) customButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) } @objc private func buttonTapped() { // 调用闭包,通知外部处理点击事件 onButtonTapped?() } }
步骤2:在主ViewController里设置闭包回调
class MainViewController: UIViewController { @IBOutlet weak var customView: TextCustomisationVC! override func viewDidLoad() { super.viewDidLoad() // 设置闭包,注意用[weak self]避免循环引用 customView.onButtonTapped = { [weak self] in guard let self = self else { return } print("自定义View按钮点击触发闭包!") self.showTapAlert() } } private func showTapAlert() { let alert = UIAlertController(title: "提示", message: "按钮点击成功", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) } }
不推荐的方式:直接暴露按钮(破坏封装,尽量避免)
虽然这种方式最简单,但会破坏自定义View的封装性——如果以后你修改自定义View内部的按钮(比如改名、替换成其他控件),主ViewController的代码会直接报错,维护性很差,所以尽量不用:
// 自定义View里把按钮设为public @IBOutlet public weak var customButton: UIButton! // 主ViewController里直接给按钮加点击事件 override func viewDidLoad() { super.viewDidLoad() customView.customButton.addTarget(self, action: #selector(customButtonTapped), for: .touchUpInside) } @objc private func customButtonTapped() { print("直接绑定按钮的点击事件") }
内容的提问来源于stack exchange,提问作者Jitendra Modi
相关产品推荐
相关产品推荐

