Search code examples
iosswiftuiscrollviewuiimageviewpinchzoom

Zoom & Pin on the same UIImageView


I have an UIImageView in UIScrollView for allow user to zoom in image. No problem in this part. I use the following code for this:

func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return self.imageView
}

Also, users can be able to pin some location in same image. I am using the following code to pin image and there is also no problem.

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first!
    let location = touch.location(in: self.imageView)
    let touchedRect = CGRect(x: location.x - 10, y: location.y - 10, width: 20, height: 20)

    let touchedInCourt = touchedRect.intersects(self.imageView.bounds)
    switch touchedInCourt {
    case true:
        if self.imageView.subviews.count > 0 {
            var flagForIntersect = false
            for subview in self.imageView.subviews {
                let subviewFrame = subview.frame
                if subviewFrame.intersects(touchedRect) {
                    subview.removeFromSuperview()
                    flagForIntersect = true
                }
            }
            if !flagForIntersect {
                addDot(withLocation: location, toPhoto: self.imageView)
            }
        } else {
            addDot(withLocation: location, toPhoto: self.imageView)
        }
    case false: break
    }
}

func addDot(withLocation location: CGPoint, toPhoto photo: UIImageView) {
    let frame = CGRect(x: location.x - 15, y: location.y - 15, width: 30, height: 30)
    let tempImageView = UIImageView(frame: frame)
    tempImageView.image = UIImage(named: "Blue Dot")
    photo.addSubview(tempImageView)
}

Using these two parts in same UIImageView causes the problem.

If scrollView.userInteractionEnable = true, zoom works but touchesEnded function not calling. On the other hand, if scrollView.userInteractionEnable = false touchesEnded function called but zoom not working.

touch.location(in:) function really useful for me, therefore I don't want to switch from UITouch to UITapGestureRecognizer.

Is there any way to do these two parts using UITouch?


Solution

  • OK, I solved the problem.

    Turns out UITapGestureRecognizer also has .location(in:) function.

    For those who are experiencing the same problem, I add the working code below.

    let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPressed))
    longPressRecognizer.minimumPressDuration = 0.5
    longPressRecognizer.delaysTouchesBegan = true
    longPressRecognizer.delegate = self
    self.imageView.addGestureRecognizer(longPressRecognizer)
    
    @objc func longPressed(sender: UILongPressGestureRecognizer) {
        if sender.state == UIGestureRecognizer.State.ended {
            let location = sender.location(in: self.imageView)
            let touchedRect = CGRect(x: location.x - 10, y: location.y - 10, width: 20, height: 20)
    
            let touchedInCourt = touchedRect.intersects(self.imageView.bounds)
            switch touchedInCourt {
            case true:
                if self.imageView.subviews.count > 0 {
                    var flagForIntersect = false
                    for subview in self.imageView.subviews {
                        let subviewFrame = subview.frame
                        if subviewFrame.intersects(touchedRect) {
                            subview.removeFromSuperview()
                            flagForIntersect = true
                        }
                    }
                    if !flagForIntersect {
                        addDot(withLocation: location, toPhoto: self.imageView)
                    }
                } else {
                    addDot(withLocation: location, toPhoto: self.imageView)
                }
            case false: break
            }
        }
    }
    

    I used UILongPressGestureRecognizer but UITapGestureRecognizer works as well.