chevi99
chevi99

Reputation: 143

How to add a parameter to UITapGestureRecognizer so that the action function can access that parameter

I have created UIViews programmatically based on the number of items i stored in my UserDefaults and each UIView represents an item from the userDefaults and have added UITapGestureRecognizer on top of it. Now this UIViews when clicked will send my user to a new view controller, now my problem is how do I pass a parameter which will hold a value so that the new view controller can determine which view was clicked. Below is my code

//Retrieving my userDefaults values
let items = preferences.object(forKey: selectedOffer)

//How i loop and create my UIViews
if let array = items as! NSArray?{
                    totalOffers = array.count
                    let castTotalOffers = CGFloat(totalOffers)
                    var topAnchorConstraint: CGFloat = 170
                    var cardHeight: CGFloat = 145
                    for obj in array {
                        if let dict = obj as? NSDictionary{
                            offerName = dict.value(forKey: "NAME") as! String
                            let offerPrice = dict.value(forKey: "PRICE") as! String
                            let offerDescription = dict.value(forKey: "DESCRIPTION") as! String

                            //creating the uiview
                            let offerView = UIView()
                            self.scrollView.addSubview(offerView)
                            offerView.translatesAutoresizingMaskIntoConstraints = false
                            offerView.topAnchor.constraint(equalTo: self.appBackImage.bottomAnchor, constant: topAnchorConstraint).isActive = true
                            offerView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 20.0).isActive = true
                            offerView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -20.0).isActive = true
                            offerView.backgroundColor = UIColor.white
                            offerView.heightAnchor.constraint(equalToConstant: 130).isActive = true
                            //transforming to cards
                            offerView.layer.cornerRadius = 2
                            offerView.layer.shadowOffset = CGSize(width: 0, height: 5)
                            offerView.layer.shadowColor = UIColor.black.cgColor
                            offerView.layer.shadowOpacity = 0.1

                            self.scrollView.contentSize.height = CGFloat(totalOffers) + topAnchorConstraint + 70


                            //Adding gesture
                            let touchRec = UITapGestureRecognizer(target: self, action: #selector(goToBuyBundle(offerClicked:offerName)))
                            offerView.addGestureRecognizer(touchRec)


                        }
                    }
                }

//Function to go to buy offer
    @objc func goToBuyBundle(_sender: UITapGestureRecognizer, offerClicked:String){
        guard let moveTo = storyboard?.instantiateViewController(withIdentifier: "BuyOfferViewController") as? BuyOfferViewController else {return}
        moveTo.selectedOffer = offerClicked
        self.addChildViewController(moveTo)
        moveTo.view.frame = self.view.frame
        self.view.addSubview(moveTo.view)
        moveTo.didMove(toParentViewController: self)
    }

Just want a way when i navigate to the next view controller i can retrieve which UIView was clicked by using the offerName. Thanks in Advance

Upvotes: 2

Views: 2355

Answers (2)

ReMeDy
ReMeDy

Reputation: 99

You could add custom variable to UITapGestureRecognizer something like:

import UIKit
private var assocKey : UInt8 = 0

extension UITapGestureRecognizer {

public var offerName:String{
    get{
        return objc_getAssociatedObject(self, &assocKey) as! String

    }
    set(newValue){
        objc_setAssociatedObject(self, &assocKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
    }
}
}

And then use it like:

...
let touchRec = UITapGestureRecognizer(target: self, action: #selector(goToBuyBundle(offerClicked:offerName)))
touchRec.offerName = offerName
offerView.addGestureRecognizer(touchRec)
...

 @objc func goToBuyBundle(_sender: UITapGestureRecognizer, offerClicked:String){
    guard let moveTo = storyboard?.instantiateViewController(withIdentifier: "BuyOfferViewController") as? BuyOfferViewController else {return}
    moveTo.selectedOffer = sender.offerName
...
}

Upvotes: 0

SWAT
SWAT

Reputation: 1158

Make your custom View and store the parameter that you want to pass through the Gesture Recognizer inside the view.

class GestureView: UIView{

var myViewValue: String? // Or whichever type of value you want to store and send via the gesture
}

When you initiate your view, add the value as per your requirement:

    let panReceptor = GestureView()
    panReceptor.myViewValue = "Hello World"

Add a simple TapGesture on this custom view and you may pass the value as below:

let tapGesture = UITapGestureRecognizer.init(target: self, action: #selector(viewTapped(sender:)))
    panReceptor.addGestureRecognizer(tapGesture)


@objc func viewTapped(sender: UITapGestureRecognizer){

    guard let unwrappedView = sender.view as? GestureView else { return }
    print("Gesture View value : \(unwrappedView.myViewValue)")
}

In the above example I have in effect passed a String parameter through the sender.view.

You may pass any type in this manner and use the value as per your requirement in the selector method.

Upvotes: 4

Related Questions