UITapGestureRecognizer 在自定义 UIView 中不工作

UITapGestureRecognizer is not working inside the custom UIView

我的 ViewController 如下所示。在这里,我调用我的自定义视图并以编程方式设置它。我面临的问题是点击手势不起作用。即使它没有被调用。

这个 [ 也与此类似,但我无法理解我的情况。我被困在这里好几个小时了。

class myViewController : ViewController {
    
    init() {
        super.init(nibName: nil, bundle: nil)
        
        self.view.addSubview(self.myView)
        
        self.myView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        self.myView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    lazy var myView : MyCustomView = {
        let view = MyCustomView(frame: CGRect(x: 0, y: 0, width: 476.0, height: 398.0))
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
}

我的自定义视图是这样的。

class MyCustomView : UIView {
  
    override init(frame: CGRect) {
        super.init(frame: frame)
             
        self.widthAnchor.constraint(equalToConstant: frame.width).isActive = true
        self.heightAnchor.constraint(equalToConstant: frame.height).isActive = true

        self.mView.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
        self.mView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    private lazy var mView: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = UIColor.init(hexString: "#EDEEEF")
        view.isUserInteractionEnabled = true
        
        let gesture = UITapGestureRecognizer(target: self, action:  #selector(tappedDropDown))
        view.addGestureRecognizer(gesture)
        
        return view
    }() 

    @objc func tappedDropDown(sender : UITapGestureRecognizer){
        print("Tapped")
    }
}

我认为问题是你在 ViewController 之外有函数 tu 运行。只需执行以下操作:

class myViewController : ViewController {

    @objc func tappedDropDown(sender : UITapGestureRecognizer){
        print("Tapped")
    }

    init() {
        super.init(nibName: nil, bundle: nil)
    
        self.view.addSubview(self.myView)
    
        self.myView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        self.myView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    lazy var myView : MyCustomView = {
        let view = MyCustomView(frame: CGRect(x: 0, y: 0, width: 476.0, height: 398.0))
        view.translatesAutoresizingMaskIntoConstraints = false

        let gesture = UITapGestureRecognizer(target: self, action:  #selector(tappedDropDown))
        view.addGestureRecognizer(gesture)

        return view
    }()
}

并且,从您的自定义中删除我在此处添加的行 class。

示例代码存在许多问题,这些问题会导致其无法正常工作,有些甚至会导致其无法编译(未终止的字符串文字、尝试设置自动布局 (AL) 约束而不将 TAMIC 设置为 false 等)。

但我认为*停止点击手势工作的问题是布局代码是框架大小和 AL 约束的混合,它并没有按照您认为的方式进行布局,这意味着自定义视图的子视图也未收到响应手势。

更改布局代码,使其全部为 AL,无需对手势识别器或其操作方法进行任何更改即可使点击手势正常工作。

我假设您的目标布局是带有子视图(您的 CustomView)的 VC 视图,该视图又具有自己的子视图(您的 mView,下面我将其重命名为 subView 以使其更清晰),在三层金字塔类型的堆栈中。

I say 'think' above because I may have corrected some other error in fixing the layout code. I've only corrected the code necessary to get it to compile and give a working UI. I've not intentionally addressed any other issue as they are not relevant to the question.

下面的代码的工作原理是它布置了三个视图(VC 的视图、myView(一个 CustomView)和 CustomView 的 subview 并将 tapGestureRecogniser 添加到 subView。轻按时,gestureRecogniser 会触发其选择器方法。它可能不会按照您想要的方式进行布局,因为很难说出您试图实现的布局,但它确实证明了 gestureRecogniser 按预期工作。

class myViewController : UIViewController {
   
   lazy var myView : MyCustomView = {MyCustomView(frame: .zero)}()
   
   init() {
      super.init(nibName: nil, bundle: nil)
      view.heightAnchor.constraint(equalToConstant: 600).isActive = true
      
      view.addSubview(myView)
      myView.topAnchor.constraint(equalTo: view.topAnchor, constant: 50).isActive = true
      myView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -50).isActive = true
      myView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -50).isActive = true
      myView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 50).isActive = true

   }
   
   required init?(coder: NSCoder) {
      fatalError("init(coder:) has not been implemented")
   }
}

class MyCustomView : UIView {
   override init(frame: CGRect) {
      super.init(frame: frame)
      backgroundColor = .systemOrange
      translatesAutoresizingMaskIntoConstraints = false
      addSubview(subView)
      subView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: -50).isActive = true
      subView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -50).isActive = true
      subView.topAnchor.constraint(equalTo: topAnchor, constant: 50).isActive = true
      subView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -50).isActive = true
   }
   
   required init?(coder aDecoder: NSCoder) {
      fatalError("init(coder:) has not been implemented")
   }
   
   private lazy var subView: UIView = {
      let view = UIView()
      view.backgroundColor = .systemBlue
      view.translatesAutoresizingMaskIntoConstraints = false
      view.isUserInteractionEnabled = true
      
      let gesture = UITapGestureRecognizer(target: self, action:  #selector(tappedDropDown))
      view.addGestureRecognizer(gesture)
      return view
   }()
   
   @objc func tappedDropDown(sender : UITapGestureRecognizer){
      print("Tapped")
   }
}