ekkeee
ekkeee

Reputation: 137

UITapGestureRecognizer not attaching action

I created a separate class for View. I left all the functions in the Controller. But when I add a click on the picture, it doesn't work for some reason.

import UIKit

class APOTDView: UIView {

    var imageView: UIImageView = {
        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.isUserInteractionEnabled = true
        let tap = UITapGestureRecognizer(target: self, action: #selector(APOTDViewController.imageTapped(_:)))
        imageView.addGestureRecognizer(tap)

        return imageView
    }()
}
import UIKit

class APOTDViewController: UIViewController {

    let av = APOTDView()

    override func viewDidLoad() {
        super.viewDidLoad()
        // ... add subview and constraint
    }

    @objc func imageTapped(_ sender: UITapGestureRecognizer) {
        print("good job")
    }
}

What's the matter? Please help me figure it out

Upvotes: 1

Views: 93

Answers (2)

Raja Kishan
Raja Kishan

Reputation: 18914

This will not work, because you are calling the UIViewController method directly without any class reference or object. The solution is to use protocol or clouser to get action from view to class.

class

class APOTDView: UIView {
    @objc var imageViewAction: ((UITapGestureRecognizer) -> Void)? = nil
    
    lazy var imageView: UIImageView = {
        let imageView = UIImageView()
        imageView.backgroundColor = .blue
        imageView.translatesAutoresizingMaskIntoConstraints = true
        imageView.isUserInteractionEnabled = true
        let tap = UITapGestureRecognizer(target: self, action: #selector((imageTapped(_:))))
        imageView.addGestureRecognizer(tap)
        return imageView
    }()
    
    @objc private func imageTapped(_ sender: UITapGestureRecognizer) {
        self.imageViewAction?(sender)
    }
}

ViewController

class APOTDViewController: UIViewController {
    let av = APOTDView()

    override func viewDidLoad() {
        super.viewDidLoad()
        av.imageViewAction = { sender in
            print("good job")
        }
    }
}

Upvotes: 1

florieger
florieger

Reputation: 1390

Your selector in the UITapGestureRecognizer is wrong. You can not call the APOTDViewController directly.
APOTDViewController.imageTapped would be a static function, which is not available.

You can use a delegate instead.

Delegate Protocol and View.

protocol APOTDViewDelegate: AnyObject {
    func viewDidTapImage()
}

class APOTDView: UIView {
    weak var delegate: APOTDViewDelegate?

    var imageView: UIImageView = {
        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.isUserInteractionEnabled = true
        let tap = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
        imageView.addGestureRecognizer(tap)

        return imageView
    }()

    @objc func imageTapped() {
        delegate?.viewDidTapImage()
    }
}

ViewController:

class APOTDViewController: UIViewController, APOTDViewDelegate {
    let av = APOTDView()

    override func viewDidLoad() {
        super.viewDidLoad()
        av.delegate = self
        // ... add subview and constraint
    }

    @objc func viewDidTapImage() {
        print("good job")
    }
}

Upvotes: 1

Related Questions