Search code examples
swiftxcodeuiimageviewuiimagepickercontrolleruigesturerecognizer

Set image of UIImageView using gestureRecognizer


I am asking if it is possible to set the image of a UIImageView using a gestureRecognizer, or is it necessary to overlay a button on top of the UIImageView.

I have an outlet collection of UIImageViews, called imageViews. There are four of these, and their tags have been set from 1 to 4. In my viewDidLoad, to add the gesture recognizer to each of the image views in the collection, i have used:

override func viewDidLoad() {
    super.viewDidLoad()

    for i in (0..<imageViews.count) {

        let imageViewTapped = UITapGestureRecognizer(target: self, action: #selector(selectImage(tap:)))
        imageViewTapped.numberOfTapsRequired = 1
        imageViews[i].addGestureRecognizer(imageViewTapped)

    }

}

Next, I created my gestureRecognizer as a function in the viewController class. This is where the image picker controller is created and where the image view that was tapped is identified:

func selectImage(tap: UITapGestureRecognizer) {

    var imagePicker = UIImagePickerController()
    imagePicker.delegate = self
    imagePicker.sourceType = .photoLibrary
    imagePicker.allowsEditing = false
    imagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
    self.present(imagePicker, animated: true, completion: nil)

    guard let viewTappedTag = tap.view?.tag else {return}
    self.selectedImageView = imageViews[viewTappedTag - 1] 

}

selectedImageView is a variable in the viewController class with a type of UIImageView. My thinking was that this variable could hold the UIImageView that was tapped, which is identified by the gestureRecognizer, as shown above. This could then be passed to the delegate later on.

Next, I created the delegates, the didFinishPickingMediaWithInfo and didCancel, though I will only show the former for brevity. Both were created inside the viewController class:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

    var chosenImage = UIImage()
    chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
    self.selectedImageView.image = chosenImage

    dismiss(animated: true, completion: nil)

}

Unfortunatley, the image of the image view that was tapped is not updated to the one that was chosen from the library. What is the correct way to do this? And I feel as though I am bloating my viewController with all of this code, can this be moved to a seperate class? Am i wrong in doing it like this, and instead one should just overlay a button?

EDIT

The best I could come up with so far is a switch statement in my imagePickerController, where imageViewOne, imageViewTwo etc are outlets for each UIImageView:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

    var chosenImage = UIImage()
    chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage

    switch self.viewTappedTag {
    case 1:
        imageViewOne.image = chosenImage
    case 2:
        imageViewTwo.image = chosenImage
    case 3:
        imageViewThree.image = chosenImage
    case 4:
        imageViewFour.image = chosenImage
    default:
        imageViewOne.image = chosenImage

    }

    dismiss(animated: true, completion: nil)

}

where viewTappedTag is a viewController class variable, the value of which is defined by the tag of the view that was tapped and is set in the gestureRecognizer. Can anyone improve on this?


Solution

  • In the end I used a switch statement to achieve my goal:

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    
    var chosenImage = UIImage()
    chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
    
    switch self.viewTappedTag {
    case 1:
        imageViewOne.image = chosenImage
    case 2:
        imageViewTwo.image = chosenImage
    case 3:
        imageViewThree.image = chosenImage
    case 4:
        imageViewFour.image = chosenImage
    default:
        imageViewOne.image = chosenImage
    
    }
    
    dismiss(animated: true, completion: nil)
    
    }