0

I have an image that I want to rotate every time the user swipes on it. It works the first time, and first time only! How is it that the view is losing the swipe gesture recognizer?

        myCircle = UIImageView( ... )
        myCircle.isUserInteractionEnabled = true

        let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(swiping(sender:)))
        swipeLeft.direction = .left
        myCircle.addGestureRecognizer(swipeLeft)
        let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(swiping(sender:)))
        swipeRight.direction = .right
        myCircle.addGestureRecognizer(swipeRight)
    }

    @objc func swiping(sender: UISwipeGestureRecognizer) {
        // this function only called the first time!
        if sender.direction == UISwipeGestureRecognizer.Direction.left {
            myCircleRotation -= CGFloat(Double.pi/2)
        } else if sender.direction == UISwipeGestureRecognizer.Direction.right {
            myCircleRotation += CGFloat(Double.pi/2)
        }
        // if I comment out this next line, function is called (correctly) every swipe!
        myCircle.transform = CGAffineTransform(rotationAngle: myCircleRotation)
    }
coco
  • 2,998
  • 1
  • 35
  • 58
  • It looks like since you are rotating the `UIImageView` and not the `UIImage`, the swipe gestures orientation appears different, because the view is rotated. If you swipe left/right it rotates 90 degrees, then you have to swipe up/down to rotate another 90 degrees again. Then you can swipe left/right again. You might want to rotate the `UIImage` instead see [here](https://stackoverflow.com/questions/1315251/how-to-rotate-a-uiimage-90-degrees) or [here](https://stackoverflow.com/questions/27092354/rotating-uiimage-in-swift/47402811#47402811) – Dennis W. Feb 02 '19 at 17:55
  • @DennisW.: Yikes, you're right! So either rotate the image itself (core graphics, bit of a pain, and can I animate the change?), or capture all 4 directions for swipe, and figure out what the user really wanted to do? – coco Feb 02 '19 at 18:15
  • There are some SO questions I linked too, that show extensions on `UIImage` to rotate it. You should be able to animate the change. I have not found a way yet to rotate the `UIImageView` and keep the gestures orientation intact. You could keep changing the swipe gestures direction from say left to bottom or right to top each time it rotates, but that feels really hacky. – Dennis W. Feb 02 '19 at 18:30
  • @DennisW. - perhaps hacky, but by switching from one image to another, I can't get a "spinning" feel to the image being rotated – coco Feb 02 '19 at 18:38
  • Maybe you should to consider adding the `UIImageView` to a container view and put the gestures in the container view? – Dennis W. Feb 02 '19 at 19:12
  • @DennisW. - YES! Thank you, that works perfectly. Are you going to write that up as an answer? – coco Feb 02 '19 at 19:36

1 Answers1

2

You can add a UIView as a container view to your hierarchy, and then add the UIGestureRecognizers to the container view instead of to the UIImageView. This would allow your image to be rotated without impact to the gestures.

import UIKit

class ImageViewController: UIViewController {

    @IBOutlet weak var myCircleView: UIImageView!
    @IBOutlet weak var containerView: UIView!

    var myCircleRotation:CGFloat = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        setupImage()
    }

    private func setupImage() {
        let image = UIImage(named: "your-image")
        myCircleView.image = image
        myCircleView.isUserInteractionEnabled = true

        let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(swiping(sender:)))
        swipeLeft.direction = .left
        containerView.addGestureRecognizer(swipeLeft)
        let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(swiping(sender:)))
        swipeRight.direction = .right
        containerView.addGestureRecognizer(swipeRight)
    }

    @objc func swiping(sender: UISwipeGestureRecognizer) {
        // this function only called the first time!
        if sender.direction == UISwipeGestureRecognizer.Direction.left {
            myCircleRotation -= CGFloat(Double.pi/2)
        } else if sender.direction == UISwipeGestureRecognizer.Direction.right {
            myCircleRotation += CGFloat(Double.pi/2)
        }

        UIView.animate(withDuration: 0.5) {
            self.myCircleView.transform = CGAffineTransform(rotationAngle: self.myCircleRotation)
        }
    }
} 
Dennis W.
  • 646
  • 6
  • 7