在 Swift 中使用 UITapGestureRecognizer 中的参数

Posted

技术标签:

【中文标题】在 Swift 中使用 UITapGestureRecognizer 中的参数【英文标题】:Using parameters in action of UITapGestureRecognizer in Swift 【发布时间】:2015-08-19 02:04:04 【问题描述】:

我正在尝试使用UITapGestureRecognizer 的操作调用带参数的函数,但我想不出任何替代方法。

这是假设使用indexPath 参数调用doubleTap 函数的手势。

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

这是假定要调用的函数。

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

如何使用indexPath 参数调用doubleTap 函数?

感谢您的所有建议。

编辑 - 这是我的全部代码,它基本上是设置对象“名称”,所以我的第二个 viewController 可以获取并使用它

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")
    

【问题讨论】:

【参考方案1】:

鉴于您有NSIndexPath,我想您想从UITableView 上的点击触摸点检索相应的indexPath

UIGestureRecognizer 有一个(或没有)参数。当提供了一个时,它会自行传递 - 但是,indexPath 不会传递给上述函数。

假设我们有以下内容:

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

以及点击视图时对应的功能:

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!"
 

更新:

这用于展示如何向视图添加手势识别器,通过它我们检索被点击两次的cell (item) 中的indexPath

回调函数被触发,我们可以在其中检查被点击的cellitem)是否是我们感兴趣的。

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(....)
        
    

另一个更新:

由于您似乎正在添加需要双击所有单元格的手势识别器,这告诉我您对双击的任何单元格感兴趣;因此,我们不需要任何条件来检查单元格是否是我们感兴趣的单元格,因为它们都是。

所以:

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)

【讨论】:

好吧,这是有道理的,除了我使用的是 UICollectionView,我猜它的过程相同,我可以得到 UICollectionCell 的 tapLocation 和 indexPath? 我似乎无法从 indexPath 获取整数。当我打印 indexPath 时,我在控制台中得到“0xc000000000000016> length = 2, path = 0 - 0”。我如何从这个 indexPath 中得到 0? indexPath.row 不起作用,它说它不是 indexPath 的成员 如果我将手势识别器添加到视图中,任何点击或双击都会触发手势,我需要它,以便每个单元格在点击或双击时都有自己的功能 条件应该放在哪里?在 doubleTap(sender: UITapGestureGecognizer) 函数中?请给我一个更具体的例子。 我在 if 条件下做了 NSLog("@", cell.tag) 并且它总是返回 null,我没有得到一个标识【参考方案2】:

实现您想要的最佳方式是获取您的点击手势的超级视图,这将为您提供正确的 indexPath。试试这个:

   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)
    

您可以根据您的层次结构级别增加或减少超级视图。

【讨论】:

实际上,这绝不是“最佳”方式。特别是考虑到问题和现有答案。【参考方案3】:

如苹果开发者文档中所述,action 参数应接收

动作::- 一个选择器,它标识目标实现的方法来处理接收器识别的手势。动作选择器必须符合类概述中描述的签名。 NULL 不是有效值。

UIGestureRecognizer.h 中描述的有效动作方法签名是:

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

因此,基本上,您将能够发送除gestureRecognizer之外的任何其他参数。

【讨论】:

【参考方案4】:

你需要做的就是调用它而不在你的字符串文字中使用任何类型的参数。

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

: 告诉计算机您正在使用带参数的函数,并且该函数是在其他地方创建的。

希望这会有所帮助:)

【讨论】:

好吧,这对我来说有点道理,但是 doubleTap func 是如何实际接收 indexPath 变量的呢? 它将通过您的操作调用。被调用的函数处理所有参数信息【参考方案5】:

除了user2277872 的回复之外,我也发现它很有用,并且仅适用于可能不熟悉的其他人 - IBAction 函数可以通过从 xib 拖动到类中的 预写 函数 - 如果需要没有参数(即没有前面提到的 : 字符),这很有用。

无参数示例

@IBAction private func somethingTapped() 
        ...

【讨论】:

以上是关于在 Swift 中使用 UITapGestureRecognizer 中的参数的主要内容,如果未能解决你的问题,请参考以下文章

如何关闭 UIPopoverController 并选择表格单元格?

单击任何 UIImage 并在 Objective-C 中打开一个 UIImageView

我可以在 Swift 3 项目中使用 Swift 2.3 框架吗?

如何在OC中使用Swift如何在Swift中使用OC

swift 优雅地处理Swift中可本地化的字符串。注意:此代码在Swift 2中,需要在现代Swift中使用更新。

在 Swift 项目中使用 Objective C 类中的 Swift 类