Cherryholme
Cherryholme

Reputation: 274

Using parameters in action of UITapGestureRecognizer in Swift

I am trying to call a function with parameters using the action of UITapGestureRecognizer and I can't figure out any alternative.

This here is the gesture that is suppose to call the doubleTap function with the indexPath parameter.

var gestureDoubleTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "doubleTap(indexPath)")

This here is the function that is suppose to be called.

func doubleTap(indexPath: NSIndexPath) {
    NSLog("double tap")
    NSLog("%@", indexPath.row)
}

How can I call the doubleTap function with the indexPath parameter?

Thank you for all suggestions.

EDIT - this is my whole code, it is basically setting up the object 'name' so my second viewController can get it and use it

import UIKit
class viewController1: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {

    @IBOutlet weak var collectionView: UICollectionView!
    var imageArray:[String] = []
    var name : AnyObject? {
        get {
        return NSUserDefaults.standardUserDefaults().objectForKey("name")
        }
        set {
            NSUserDefaults.standardUserDefaults().setObject(newValue!, forKey: "name")
            NSUserDefaults.standardUserDefaults().synchronize()
        }
    }

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return imageArray.count
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        var cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as myViewCell

        //adding single and double tap gestures for each cell
        /////////////////////////////
        //ISSUE IS SENDING indexPath TO doubleTap FUNC
        var gestureDoubleTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "doubleTap:")
        gestureDoubleTap.numberOfTapsRequired = 2
        cell.addGestureRecognizer(gestureDoubleTap)

        var gestureSingleTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "singleTap")
        gestureSingleTap.numberOfTapsRequired = 1
        cell.addGestureRecognizer(gestureSingleTap)

        cell.imgView.image=UIImage(named: imageArray[indexPath.row])        
        return cell
    }

    //func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath){
    //
    //    name = imageArray[indexPath.row]
    //}

    override func viewDidLoad(){
        super.viewDidLoad()
        imageArray=["1.png","2.png","2.png","1.png","1.png","2.png","1.png","2.png","1.png","2.png","1.png","2.png","1.png","2.png","1.png","2.png"]

    }

    func doubleTap(sender: UITapGestureRecognizer) {
        var tapLocation = sender.locationInView(self.collectionView)

        var indexPath:NSIndexPath = self.collectionView.indexPathForItemAtPoint(tapLocation)!

        //var cell = self.collectionView.cellForItemAtIndexPath(indexPath)

        NSLog("double tap")
        NSLog("%@", indexPath)

        //NSLog("%@", cell!)
        //THIS IS THE GOAL----- set 'name' with the appropriate img      corresponding the cell
        //name = imageArray[indexPath]
        //self.performSegueWithIdentifier("segue", sender: nil)
    }

    func singleTap() {
        NSLog("single tap")
    }
}

Upvotes: 18

Views: 25795

Answers (5)

michaelrbg
michaelrbg

Reputation: 89

Further to user2277872's response that I also found useful, and just for anyone else who may not be familiar - IBAction functions can also be connected by dragging from the xib to a prewritten function in the class - this is useful if no parameters are desired (i.e. without the : character that was previously mentioned).

Example with no parameters

@IBAction private func somethingTapped() {
        ...
}

Upvotes: 0

user2277872
user2277872

Reputation: 2973

All you need to do is call it without using any kind of parameters in your string literal.

var gestureDoubleTap = UITapGestureRecognizer(target: self, action: "doubleTap:")

The : tells the computer that you're using a function with a parameter, and that is created somewhere else.

Hope this helps :)

Upvotes: 0

Uriel
Uriel

Reputation: 71

The Best way to achieve what you wish is get the superview of your tap gesture, this will give you the correct indexPath. Try this:

   func doubleTap(sender: UITapGestureRecognizer) {
        let point = sender.view
        let mainCell = point?.superview
        let main = mainCell?.superview
        let cell: myViewCell = main as! myViewCell
        let indexPath = collectionView.indexPathForCell(cell)
    }

You can increase or reduce the superview's depending on you hierarchy level.

Upvotes: 3

Unheilig
Unheilig

Reputation: 16292

Given that you have NSIndexPath, I suppose you would like to retrieve the corresponding indexPath from the tap touch point on your UITableView.

UIGestureRecognizer has one (or no) parameter. When there is one provided, it passes itself - the indexPath is, however, not passed to the function as mentioned.

Let's say we have the following:

let aTap = UITapGestureRecognizer(target: self, action: "tapped:")

and the corresponding function when the view is tapped on:

func tapped(sender: UITapGestureRecognizer)
{
    //using sender, we can get the point in respect to the table view
    let tapLocation = sender.locationInView(self.tableView)

    //using the tapLocation, we retrieve the corresponding indexPath
    let indexPath = self.tableView.indexPathForRowAtPoint(tapLocation)

    //finally, we print out the value
    print(indexPath)

    //we could even get the cell from the index, too
    let cell = self.tableView.cellForRowAtIndexPath(indexPath!)

    cell.textLabel?.text = "Hello, Cell!"
 }

Update:

This serves to show how to add a gesture recognizer to the view, through which we retrieve the indexPath of the cell (item) that was tapped on twice.

The callback function is triggered, within which we could check whether or not the cell (item) that was tapped on is the one we are interested in.

override func viewDidLoad()
{
    super.viewDidLoad()

    let doubleTaps = UITapGestureRecognizer(target: self, action: "doubleTapTriggered:")
    doubleTaps.numberOfTapsRequired = 2
    self.view.addGestureRecognizer(doubleTaps)
}

func doubleTapTriggered(sender : UITapGestureRecognizer)
{
    var tapLocation = sender.locationInView(self.collectionView)
    var indexPath : NSIndexPath = self.collectionView.indexPathForItemAtPoint(tapLocation)!

    if let cell = self.collectionView.cellForItemAtIndexPath(indexPath)
    {
        if(cell.tag == 100)
        {
            print("Hello, I am cell with tag 100")
        }
        else if(cell.tag == 99)
        {
            print("Hello, I am cell with tag 99")
            //We could do something, then, with the cell that we are interested in.
            //I.e., cell.contentView.addSubview(....)
        }
    }
}

Another Update:

Since it appears that you are adding gesture recognizer that requires double taps to all cells, which tells me that you are interested in any cell that was double-tapped on; and so, we would't need any condition to check whether or not the cells are the ones we are interested in, because they all are.

And so:

func doubleTapTriggered(sender : UITapGestureRecognizer)
{
    var tapLocation = sender.locationInView(self.collectionView)
    var indexPath : NSIndexPath = self.collectionView.indexPathForItemAtPoint(tapLocation)!

    name = imageArray[indexPath]
    self.performSegueWithIdentifier("segue", sender: nil)
}

Upvotes: 44

Vikas Dadheech
Vikas Dadheech

Reputation: 1720

As described in apple developer documents, the action parameter should receive

action::- A selector that identifies the method implemented by the target to handle the gesture recognized by the receiver. The action selector must conform to the signature described in the class overview. NULL is not a valid value.

And Valid action method signatures described in UIGestureRecognizer.h are:

// -(void)handleGesture; // -(void)handleGesture:(UIGestureRecognizer*)gestureRecognizer;

So basically, you will not be able to send anything else as the parameter except the gestureRecognizer.

Upvotes: 0

Related Questions