Personnellement, je préfère la méthode d'écriture d'une extension pour UILabel. C'est ce que j'utilise.
import UIKit
extension UILabel {
    /**
     * A map of actions, mapped as [ instanceIdentifier : action ].
     */
    private static var _tapHandlers = [String:(()->Void)]()
    /**
     * Retrieve the address for this UILabel as a String.
     */
    private func getAddressAsString() -> String {
        let addr = Unmanaged.passUnretained(self).toOpaque()
        return "\(addr)"
    }
    /**
     * Set the on tapped event for the label
     */
    func setOnTapped(_ handler: @escaping (()->Void)) {
        UILabel._tapHandlers[getAddressAsString()] = handler
        let gr = UITapGestureRecognizer(target: self, action: #selector(onTapped))
        gr.numberOfTapsRequired = 1
        self.addGestureRecognizer(gr)
        self.isUserInteractionEnabled = true
    }
    /**
     * Handle the tap event.
     */
    @objc private func onTapped() {
        UILabel._tapHandlers[self.getAddressAsString()]?()
    }
}
Vous l'utiliseriez alors comme ceci à partir de n'importe quelle instance UILabel:
myLabel.setOnTapped {
    // do something
}
Cela peut potentiellement provoquer des fuites de mémoire, je crois, mais je n'ai pas encore déterminé la meilleure façon de les résoudre.
     
              
userInteractionEnabled = true