Where do you declare UITapGestureRecognizer() in r

2019-08-22 02:29发布

问题:

Problem

centerLabelGesture is being defined outside of the scope of viewDidLoad(), so at the time that .addGestureRecognizer(centerLabelGesture) is called, centerLabelGesture is not defined yet.

import UIKit
import SnapKit

class ViewController: UIViewController {

    var screen: UIView!
    var centerLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        screen = UIView()
        centerLabel = UILabel()

        view.addSubview(screen)
        screen.addSubview(centerLabel)

        screen.backgroundColor = .white
        screen.snp.makeConstraints { (make) in
            make.top.equalTo(view)
            make.right.equalTo(view)
            make.left.equalTo(view)
            make.bottom.equalTo(view)
        }

        centerLabel.text = "I hope I'm centered."
        centerLabel.snp.makeConstraints { (make) in
            make.center.equalTo(screen)
        }
        centerLabel.isUserInteractionEnabled = true
        centerLabel.addGestureRecognizer(centerLabelGesture)
    }

    let centerLabelGesture = UITapGestureRecognizer(target: self, action: #selector(centerLabelTapped))

    @objc func centerLabelTapped() {
        centerLabel.text = "Ouch, you tapped me!"
    }

}

Update 1/19/2019

matt pointed out that centerLabelGesture needs to be declared prior to centerLabel.addGestureRecognizer(centerLabelGesture), inside viewDidLoad()

回答1:

This is a subtle mistake. The problem is the place you've put this line:

let centerLabelGesture = UITapGestureRecognizer(target: self, action: #selector(centerLabelTapped))

Move that line into the viewDidLoad code:

centerLabel.isUserInteractionEnabled = true
let centerLabelGesture = UITapGestureRecognizer(target: self, action: #selector(centerLabelTapped))
centerLabel.addGestureRecognizer(centerLabelGesture)

The reason is that where you've got that line, it's an instance property, and when you say self as the target in an instance property initializer, it doesn't mean what you think it does (it means the class, not the instance), so the message when you tap is misdirected and does nothing.

I have filed a bug on this issue; in my opinion the compiler should at least warn you that you're making a potential mistake.



回答2:

Try adding this line in viewDidLoad

centerLabelGesture.numberOfTapsRequired = 1