UIImageView and TapGesture in Swift 3

Hello, Everyone,

I tried everthing to trigger a tap gesture recognizer in my code but until know I don't have succeeded.

Please can you help me to understand what I'm doing wrong ?


I call a image and do a zoom in the image, and want to trigger a zoom out to return the normal image.


let zoomingImageView = UIImageView(frame: startFrame!)
        zoomingImageView.backgroundColor = .red
        zoomingImageView.image = startingImageView.image
     
        zoomingImageView.isUserInteractionEnabled = true
        let gesture = UITapGestureRecognizer(target: self, action: #selector(handleZoomOut(sender:)))
        zoomingImageView.addGestureRecognizer(gesture)



func handleZoomOut(sender: UITapGestureRecognizer) {
        print("print zoom out")
      
      
    }


Thank you for all help.

This is just a guess, but would you need to mark the action method/function as an @IBAction or as @objc so that it is visible to the objective-C runtime?

I tried everthing to trigger a tap gesture recognizer in my code but until know I don't have succeeded.

Can you explain the symptoms of this failure? If LCS’s guess is right, you should see an unrecognised selector exception. If you don’t see that, there’s probably some other issue in play.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Tks @LCS and @eskimo,

I'm not using Storyboard to do a component. The output don't show any error and the application don't brake too.

It's like that the option isUserInteractionEnabled don't do what need to do.

I'll post all my class to help :



import UIKit
class ImagePlayerView: UIImageView {
   
    let view: UIView = {
        let view = UIView()
        view.backgroundColor = .blue
       
        return view
    }()
   
    let activityIndicatorView: UIActivityIndicatorView = {
        let aiv = UIActivityIndicatorView(activityIndicatorStyle: .white)
        aiv.translatesAutoresizingMaskIntoConstraints = false
        aiv.startAnimating()
        return aiv
    }()
   
    let controlsContainerView: UIView = {
        let view  = UIView()
        view.backgroundColor = UIColor(white: 0, alpha : 1)
        return view
    }()
   
    var fullImageView: UIImageView = {
       
        let iv = UIImageView()
        iv.contentMode = .scaleAspectFit
        
        iv.isUserInteractionEnabled = true
        iv.translatesAutoresizingMaskIntoConstraints = false
       
        return iv
    }()
   
   
   
    override init(frame: CGRect){
        super.init(frame: frame)
       
       
        controlsContainerView.frame = frame
        addSubview(controlsContainerView)
       
        controlsContainerView.addSubview(fullImageView)
       
        fullImageView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        fullImageView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
        fullImageView.widthAnchor.constraint(equalToConstant: 50).isActive = true
        fullImageView.heightAnchor.constraint(equalToConstant: 50).isActive = true
       
    }
    
   
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
   
  
   
}
class ImageLaucher:NSObject{
   
    func showImage(startingImageView : UIImageView){
       
       
        let startFrame = startingImageView.superview?.convert(startingImageView.frame, to: nil)
       
        let zoomingImageView = UIImageView(frame: startFrame!)
        zoomingImageView.backgroundColor = .red
        zoomingImageView.image = startingImageView.image
       
        zoomingImageView.isUserInteractionEnabled = true
        let gesture = UITapGestureRecognizer(target: self, action: #selector(handleZoomOut(sender:)))
        zoomingImageView.addGestureRecognizer(gesture)
       
       
        if let keyWindow = UIApplication.shared.keyWindow {
            let blackBackgroundView = UIView(frame: keyWindow.frame)
            blackBackgroundView.backgroundColor = .black
       
            blackBackgroundView.alpha = 0
           
            keyWindow.addSubview(blackBackgroundView)
           
            keyWindow.addSubview(zoomingImageView)
           
            UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseOut, animations: {
               
                blackBackgroundView.alpha = 1
                let height = (startFrame?.height)! / startFrame!.width * keyWindow.frame.width
               
                zoomingImageView.frame = CGRect(x: 0, y: 0, width: keyWindow.frame.width, height: height)
                zoomingImageView.center = keyWindow.center
               
            }, completion: nil)
           
        }
       
      
    }
   
    func handleZoomOut(sender: UITapGestureRecognizer) {
        print("print zoom out")
       
       
    }
   
   
}



Tks again.

I don't know if this contributes to the gesture recognizer problem, but one issue in your code is that you are using the frames of views/windows when you probably want the bounds instead.


The frame (and center) of a view represents its size and placement in the coordinates of its superview, and the bounds represents its area in its own coordinate system.


When you use keyWindow.frame and keyWindow.center in your code, the result is in the coordinates of the screen which may not be the same as keyWindows own coordinate system.


You want the frames of your subviews to be set in terms of the bounds of keyWindow.


For example, blackBackgroundView should use the bounds of keyWindow for its frame.

let blackBackgroundView = UIView(frame: keyWindow.bounds)


You would probably also want to use keyWindow.bounds.width in your aspect ratio calculation and when setting the zooming view/s frame, and you would need to convert keyWindow.center into keyWindow's coordinates from the screen coordinates.

zoomingImageView.center = keyWindow.convert(keyWindow.center, from: nil)




One other thing that would help to make your code cleaner (but isn't causing any problems at the moment), would be to force the value of startingFrame to be non-optional right away instead of repeatedly dealing with it later.


let startFrame = startingImageView.superview!.convert(startingImageView.frame, to: nil)


That way, if superview is nil you will just crash at that point instead of the next line (since startFrame would be nil), and don't have to keep dealing with startFrame as an optional for the rest of your code.

Thank you for all your advices , I'll do the changes.


I Think the problem with the gesture is doing because when I do the zoom the application is lost the context....

Just to post a solution :

I forgot to put context in cell before call showImage function 😟


cell.pacienteDetalheCell = self


But code is work know.


Tks all

UIImageView and TapGesture in Swift 3
 
 
Q