如何从UIView访问主ViewController中的tapRecognizer并禁用?
最简单的几种实现方式
首先得明确:虽然你的tapRecognizer是用let声明的,但它的isEnabled属性是可变的——我们只需要在另一个UIView里触发对这个属性的修改就行,完全不用重新赋值tapRecognizer本身。下面是几种简单的方案,按推荐程度排序:
方案1:闭包回调(最简洁,无耦合)
这是我最推荐的方式,不用让UIView知道ViewController的存在,耦合度极低:
- 在你的独立UIView类里,定义一个闭包属性,用来触发禁用操作:
class CustomView: UIView { // 定义闭包,用来通知外部执行禁用tap的操作 var disableTapAction: (() -> Void)? // 假设你在某个时机需要禁用tap,比如用户点击了这个view里的某个按钮 @objc func onSomeButtonTap() { // 调用闭包,通知外部执行禁用 disableTapAction?() } }
- 在主ViewController里创建这个CustomView的时候,把闭包赋值为禁用tapRecognizer的逻辑:
class MainVC: UIViewController { // 这里你的tapRecognizer是let声明的,完全没问题 let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap)) override func viewDidLoad() { super.viewDidLoad() // 先把tapRecognizer添加到视图上 view.addGestureRecognizer(tapRecognizer) // 创建你的独立UIView let customView = CustomView(frame: CGRect(x: 0, y: 0, width: 200, height: 200)) // 赋值闭包,直接修改tapRecognizer的isEnabled customView.disableTapAction = { [weak self] in self?.tapRecognizer.isEnabled = false } view.addSubview(customView) } @objc func handleTap() { // 你的tap处理逻辑 } }
这种方式的好处是,CustomView不需要知道MainVC的任何细节,只负责在需要的时候触发闭包,完全解耦。
方案2:弱引用ViewController(适合简单场景)
如果你的场景很简单,也可以让CustomView持有MainVC的弱引用,直接调用VC里的方法或者修改tapRecognizer:
- 在CustomView里添加弱引用的VC属性:
class CustomView: UIView { // 必须用weak避免循环引用 weak var parentVC: MainVC? @objc func onSomeButtonTap() { // 直接修改VC里的tapRecognizer的isEnabled parentVC?.tapRecognizer.isEnabled = false } }
- 在MainVC里创建CustomView时,把self赋值给parentVC:
override func viewDidLoad() { super.viewDidLoad() view.addGestureRecognizer(tapRecognizer) let customView = CustomView(frame: CGRect(x: 0, y: 0, width: 200, height: 200)) customView.parentVC = self view.addSubview(customView) }
这种方式比闭包稍微耦合一点,但代码量也很少,适合简单的场景。一定要记得用weak修饰parentVC,不然会导致循环引用、内存泄漏。
方案3:通知中心(适合跨多层级的场景)
如果你的CustomView和MainVC层级很深,或者不想有直接引用,也可以用NotificationCenter:
- 在MainVC里监听一个自定义通知:
override func viewDidLoad() { super.viewDidLoad() view.addGestureRecognizer(tapRecognizer) // 监听通知 NotificationCenter.default.addObserver(self, selector: #selector(disableTap), name: NSNotification.Name("DisableTapRecognizer"), object: nil) // 创建CustomView... } @objc func disableTap() { tapRecognizer.isEnabled = false } // 记得在deinit里移除监听,避免野指针 deinit { NotificationCenter.default.removeObserver(self) }
- 在CustomView里发送通知:
@objc func onSomeButtonTap() { NotificationCenter.default.post(name: NSNotification.Name("DisableTapRecognizer"), object: nil) }
这种方式耦合度最低,但如果项目里通知太多,可能会不好维护,所以优先用前两种方案。
内容的提问来源于stack exchange,提问作者user7186765
相关产品推荐
相关产品推荐

