我在 ImageView 子类中定义手势识别器,但在 ViewController 中调用方法会因 "unrecognized selector" 而崩溃

I am defining gesture recognizers in an ImageView subclass but calling a method in the ViewController crashes with "unrecognized selector"

我在 ImageView 子 class 中定义手势识别器,但在 ViewController 中调用方法会因 "unrecognized selector" 而崩溃。如果我在 VC 中定义手势,手势会起作用,但我试图将代码放在自定义视图 class 中以减少混乱。

这可能吗?这就是我正在做的:

class DetailPhotoImageView: UIImageView {

func setupGestures(){

    let tapped = UITapGestureRecognizer(target: self, action: #selector(TripDetailVC.tapped(_:)))
    tapped.numberOfTapsRequired = 2

    addGestureRecognizer(tapped)

    }
}

然后在 VC 我有这个函数并调用 imageView.setupGestures()

func tapped(_ gesture:UIGestureRecognizer) {
    if let tapGesture = gesture as? UITapGestureRecognizer {
        switch tapGesture.numberOfTapsRequired {
        case 2:
            print("Worked")
        default:
            break
        }
    }
}

为你的 UIImageView 制定一个接受手势的协议,并将你的 ViewController 设置为委托(将 ImageView 作为参数也是一种很好的做法..或常见):

protocol DetailPhotoDelegate {  
    func detailPhoto(_ detailPhoto: DetailPhotoImageView, actionFor gesture: UITapGestureRecognizer)
}

向您的 UIImageView 子类添加一个委托变量,并在点击视图时执行您的协议函数。另外,请确保您的 UIImageView 是 UIGestureRecognizerDelegate。

class DetailPhotoImageView: UIImageView, UIGestureRecognizerDelegate {

    var delegate: DetailPhotoDelegate?

    func setupGestures() {
        let tap =  UITapGestureRecognizer(target: self, action: #selector(someAction(_:)))
        tap.delegate = self
        tap.numberOfTapsRequired = taps
        addGestureRecognizer(tap)
    }

    func someAction(_ guesture: UITapGestureRecognizer) {
        print("tap - subclass func")
        guard let aDelegate = aDelegate else { assertionFailure(); return }

        delegate.detailPhoto(self, actionFor: gesture)
    }
}

然后将协议添加到您的 ViewController,在执行操作之前的某处将其设置为您的 DetailPhotoImageView 的委托(例如,我在 viewDidLoad() 中完成),并实现协议方法愿望:

class ViewController: UIViewController, DetailPhotoDelegate {

    @IBAction weak var detailPhoto: DetailPhotoImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        detailPhoto.delegate = self
    }

    // Mark: DetailPhotoDelegate
    func detailPhoto(_ detailPhoto: DetailPhotoImageView, actionFor guesture: UITapGestureRecognizer) {

        switch guesture.numberOfTapsRequired {
        case 1: print("1 tap"); return
        case 2: print("2 taps"); return
        default: print("\(guesture.numberOfTapsRequired) taps"); return
        }
    }

我认为目标不应该是自己

所以按照 Randall Wang 的建议,他们是对的,你也可以换一种方式,space-省钱。将 viewController 作为参数传递并将其设置为目标:

class DetailPhotoImageView: UIImageView, UIGestureRecognizerDelegate {

    func setupGestures(_ target: UIViewController) {
        guard let aTarget = target as? MyViewController else { return }

        let tap =  UITapGestureRecognizer(target: aTarget, action: #selector(aTarget.someAction(_:)))
        tap.delegate = self
        tap.numberOfTapsRequired = taps
        addGestureRecognizer(tap)
    }
}

在你的 viewController class:

detailPhoto.setupGestures(self)