如何在 Swift 中长按时选择表格行

Posted

技术标签:

【中文标题】如何在 Swift 中长按时选择表格行【英文标题】:How To select a table row during a long press in Swift 【发布时间】:2015-06-15 07:13:04 【问题描述】:

我有一个表格,它有一个长按手势识别器,它根据选择的表格行运行代码。

我遇到的麻烦是我目前必须点击我想要的行然后长按。

如何让表格选择我长按的行,而无需先点击选择它?

【问题讨论】:

【参考方案1】:

Swift 4 和 5

override func viewDidLoad() 
    super.viewDidLoad()
    setupLongPressGesture()


func setupLongPressGesture() 
    let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.handleLongPress))
    longPressGesture.minimumPressDuration = 1.0 // 1 second press
    longPressGesture.delegate = self
    self.tblMessage.addGestureRecognizer(longPressGesture)


@objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer)
    if gestureRecognizer.state == .began 
        let touchPoint = gestureRecognizer.location(in: self.tblMessage)
        if let indexPath = tblMessage.indexPathForRow(at: touchPoint) 
            
        
    

斯威夫特 3

override func viewDidLoad() 
    super.viewDidLoad()
    setupLongPressGesture()


func setupLongPressGesture() 
    let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(YourViewController.handleLongPress(_:)))
    longPressGesture.minimumPressDuration = 1.0 // 1 second press
    longPressGesture.delegate = self
    self.tblMessage.addGestureRecognizer(longPressGesture)


func handleLongPress(_ longPressGestureRecognizer: UILongPressGestureRecognizer) 
    
    if longPressGestureRecognizer.state == UIGestureRecognizerState.Began 
        
        let touchPoint = longPressGestureRecognizer.locationInView(self.view)
        if let indexPath = tableView.indexPathForRowAtPoint(touchPoint) 
            
            // your code here, get the row for the indexPath or do whatever you want
        
    

目标 - C

UILongPressGestureRecognizer* longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPress:)];
[self.tableView addGestureRecognizer:longPressRecognizer];

-(void)onLongPress:(UILongPressGestureRecognizer*)pGesture

    if (pGesture.state == UIGestureRecognizerStateRecognized)
    
    //Do something to tell the user!
    

    if (pGesture.state == UIGestureRecognizerStateEnded)
    
        UITableView* tableView = (UITableView*)self.view;
        CGPoint touchPoint = [pGesture locationInView:self.view];
        NSIndexPath* row = [tableView indexPathForRowAtPoint:touchPoint];
        if (row != nil) 
        //Handle the long press on row
        
    

【讨论】:

在 5 秒内为我工作。 Swift 4 谢谢好友!! 需要修复 Swift 4 的示例。需要删除行 'longPressGesture.delegate = self' 和 .end 替换 .began 我同意@DronPop。我确认 Swift4 不需要“longPressGesture.delegate = self”。另外我也觉得'.began'比较合适。无论如何,这是一个很好的答案,所以我投了赞成票。 我不知道为什么,但我得到 indexPathForRowAtPoint 值为零【参考方案2】:

以下代码对我来说很好用:

在 viewDidLoad 中添加长按手势识别器:

// tapRecognizer, placed in viewDidLoad
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: "longPress:")
self.view.addGestureRecognizer(longPressRecognizer)

那么长按调用的方法是这样的:

//Called, when long press occurred
func longPress(longPressGestureRecognizer: UILongPressGestureRecognizer) 

    if longPressGestureRecognizer.state == UIGestureRecognizerState.Began 

        let touchPoint = longPressGestureRecognizer.locationInView(self.view)
        if let indexPath = tableView.indexPathForRowAtPoint(touchPoint) 

            // your code here, get the row for the indexPath or do whatever you want
    

【讨论】:

他已经实现了功能并面临额外的点击问题。 我不确定我是否正确理解了这个问题。我至少可以说的是,我用我的代码长按,我得到了我长按所在行的 indexPath。无需额外点击。 let touchPoint = longPressGestureRecognizer.locationInView(self.tableView) 是正确的,而不是 let touchPoint = longPressGestureRecognizer.locationInView(self.view)。否则,您不会考虑到self.tableView.frame.origin 不能等于CGPointZero【参考方案3】:

Swift 3 功能:

func handleLongPress(_ longPressGestureRecognizer: UILongPressGestureRecognizer) 

    if longPressGestureRecognizer.state == UIGestureRecognizerState.Began 

        let touchPoint = longPressGestureRecognizer.locationInView(self.view)
        if let indexPath = tableView.indexPathForRowAtPoint(touchPoint) 

            // your code here, get the row for the indexPath or do whatever you want
    

viewDidLoad:

let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(YourViewController.handleLongPress(_:)))
longPressGesture.minimumPressDuration = 1.0 // 1 second press
longPressGesture.delegate = self
self.tableView.addGestureRecognizer(longPressGesture)

更多:https://github.com/apple/swift-evolution/blob/e4328889a9643100177aef19f6f428855c5d0cf2/proposals/0046-first-label.md

【讨论】:

如您所说,它不适用于 swift 3.0。它仍然指向 swift 对我来说在 Swift 3 中完美运行。【参考方案4】:

Swift 4

let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPressed(sender:)))
self.view.addGestureRecognizer(longPressRecognizer)

// MARK:动作

@objc func longPressed(sender: UILongPressGestureRecognizer) 

    if sender.state == UIGestureRecognizerState.began 

        let touchPoint = sender.location(in: self.tableView)
        if let indexPath = tableView.indexPathForRow(at: touchPoint) 

            print("Long pressed row: \(indexPath.row)")
        
    

【讨论】:

sender.location(in: self.tableView) // 正确【参考方案5】:

适用于 swift 版本 3

func longPress(_ longPressGestureRecognizer: UILongPressGestureRecognizer) 
    if longPressGestureRecognizer.state == UIGestureRecognizerState.began 
        let touchPoint = longPressGestureRecognizer.location(in: self.view)
        if let indexPath = notificationTabelView.indexPathForRow(at: touchPoint) 
            print("indexPath=\(indexPath)")
            // your code here, get the row for the indexPath or do whatever you want
        
    

在您的viewDidLoad 函数中

let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(EmployeeNotificationViewController.longPress(_:)))
    longPressGesture.minimumPressDuration = 1.0 // 1 second press
    longPressGesture.delegate = self as? UIGestureRecognizerDelegate
    self.notificationTabelView.addGestureRecognizer(longPressGesture)

【讨论】:

【参考方案6】:

为避免这种情况,您可以在cellForRowAtIndexPath 中添加UILongPressGestureRecognizer 而不是didSelectRowAtIndexPath

【讨论】:

【参考方案7】:

使用 IBAction 你可以做(​​对于 CollectionView):

@IBAction func handleLongPress(sender: AnyObject) 

    if sender.state == UIGestureRecognizerState.Began
    
        let position = sender.locationInView(sender.view)

        if let indexPath : NSIndexPath = ((sender.view as! UICollectionView).indexPathForItemAtPoint(position))!
            print("You holding cell #\(indexPath.item)!")
        
    

记得链接你的长按手势识别器。

【讨论】:

【参考方案8】:
let longPressGesture = UILongPressGestureRecognizer(target: self, action: (#selector(YourCustomeTableCell.longTap)))
self.addGestureRecognizer(longPressGesture)

func longTap()
    print("Long tap")

【讨论】:

【参考方案9】:

斯威夫特 5

像这样在viewDidLoad() 中声明这一行

override func viewDidLoad() 
        super.viewDidLoad()
//do other stuff here
        
        // long press listener for tableview
        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(sender:)))
        tableView.addGestureRecognizer(longPress)
        
    

handleLongPress() 方法在哪里

 @objc private func handleLongPress(sender: UILongPressGestureRecognizer) 
        if sender.state == .began 
            let touchPoint = sender.location(in: tableView)
            if let indexPath = tableView.indexPathForRow(at: touchPoint) 
                let alert = UIAlertController(title: "Alert", message: "Do you want to delete this item?", preferredStyle: .alert)
                
                let action = UIAlertAction(title: "Yes", style: .default)  (action) in
                    // do your functionality

                    alert.dismiss(animated: true, completion: nil)
                    
                
                let actionDelete = UIAlertAction(title: "No", style: .default)  (action) in
                    // do your functionality
                    alert.dismiss(animated: true, completion: nil)
                    
                

                alert.addAction(action)
                alert.addAction(actionDelete)
                self.present(alert, animated: true, completion: nil)
                // your code here, get the row for the indexPath or do whatever you want
            
        
    

【讨论】:

以上是关于如何在 Swift 中长按时选择表格行的主要内容,如果未能解决你的问题,请参考以下文章

如何使用选择器在长按时“永久”突出显示 ListView 行,但在正常按下时短暂显示

如何在 Swift 中同步表格视图和搜索栏选择?

如何在swift 3的表格视图中仅更改选定行和未选定行的字体颜色和大小?

根据在 swift 中选择的第一个表格行更改第二个表格内容

如何使用 Swift 在 XCode UI 自动化中选择随机表格视图单元格

Swift 3:如何在表格视图的多个部分中使用操作按钮?