You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从UIView访问主ViewController中的tapRecognizer并禁用?

最简单的几种实现方式

首先得明确:虽然你的tapRecognizer是用let声明的,但它的isEnabled属性是可变的——我们只需要在另一个UIView里触发对这个属性的修改就行,完全不用重新赋值tapRecognizer本身。下面是几种简单的方案,按推荐程度排序:

方案1:闭包回调(最简洁,无耦合)

这是我最推荐的方式,不用让UIView知道ViewController的存在,耦合度极低:

  1. 在你的独立UIView类里,定义一个闭包属性,用来触发禁用操作:
class CustomView: UIView {
    // 定义闭包,用来通知外部执行禁用tap的操作
    var disableTapAction: (() -> Void)?
    
    // 假设你在某个时机需要禁用tap,比如用户点击了这个view里的某个按钮
    @objc func onSomeButtonTap() {
        // 调用闭包,通知外部执行禁用
        disableTapAction?()
    }
}
  1. 在主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:

  1. 在CustomView里添加弱引用的VC属性:
class CustomView: UIView {
    // 必须用weak避免循环引用
    weak var parentVC: MainVC?
    
    @objc func onSomeButtonTap() {
        // 直接修改VC里的tapRecognizer的isEnabled
        parentVC?.tapRecognizer.isEnabled = false
    }
}
  1. 在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:

  1. 在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)
}
  1. 在CustomView里发送通知:
@objc func onSomeButtonTap() {
    NotificationCenter.default.post(name: NSNotification.Name("DisableTapRecognizer"), object: nil)
}

这种方式耦合度最低,但如果项目里通知太多,可能会不好维护,所以优先用前两种方案。


内容的提问来源于stack exchange,提问作者user7186765

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:26:45