【问题标题】:Detecting a tap on UILabel inside a cell检测单元格内对 UILabel 的点击
【发布时间】:2017-06-13 14:28:23
【问题描述】:

我在标签上有一个 UITapGestureRecognizer:

cell.label.userInteractionEnabled = true
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.labelTapped))
cell.label.addGestureRecognizer(gestureRecognizer)

我希望它在用户点击它时更改文本。在 Stackoverflow 上寻找答案数小时后,我已经到了可以更改标签文本的地步。但它也会更改其他单元格标签上的文本。这是我实现的:

 func labelTapped(recognizer: UIGestureRecognizer){
        print("Label tapped.")

        let position: CGPoint =  recognizer.locationInView(self.tableView)
        let indexPath: NSIndexPath = self.tableView.indexPathForRowAtPoint(position)!
        let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! DataTableViewCell
        
        cell.label.text = "Test."
    }

帮我找到解决办法。

【问题讨论】:

  • 您是否尝试将 sender 参数添加到手势识别器目标操作?您可以检查发件人是否为 UILabel 并仅修改该实例。
  • iOS 单元格是可重复使用的。在显示每个单元格时,您必须检查标签是否已被点击。
  • @Emptyless 我相信recognizer: UIGestureRecognizer 可以作为发件人使用。但是如何检查发件人是否是 UILabel?你的意思是没有使用cellindexPath 来检测这里的特定单元格?
  • @Caleb 我用哪种方法检查它? cellForRowAtIndexPath 会好吗?如果是这样,我如何检测标签是否在cellForRowAtIndexPath中被点击?

标签: ios swift uitableview uitapgesturerecognizer


【解决方案1】:

我建议将 DataSource 更改为 Sneak 已经提到的。然后,您可以在指定的 IndexPaths 处重新加载 tableView 以获得所需的结果:

func handleLabelTap(sender: UIGestureRecognizer) {
    // Get references
    guard let label = sender.view as? UILabel else {
        print("Error not a label")
        return
    }
    let position = sender.location(in: self.tableView)
    guard let index = self.tableView.indexPathForRow(at: position) else { 
        print("Error label not in tableView")
        return
     }

    // Notify TableView of pending updates
    self.tableView.beginUpdates()
    defer { self.tableView.endUpdates() }

    // Alter Datasource
    self.data[index.row] = "Changed Value"
    self.tableView.reloadRows(at: [index], with: .automatic)
}

self.data 是一个字符串数组,代表您的数据源。

编辑:在 cmets 中建议的 Swift 2.3 版本。

func handleLabelTap(sender: UIGestureRecognizer) {
    // Get references
    guard let label = sender.view as? UILabel else {
        print("Error not a label")
        return
    } 
    let position = sender.locationInView(self.tableView) 
    guard let index = self.tableView.indexPathForRowAtPoint(position) else { 
        print("Error label not in tableView")
        return
    } 

    // Notify TableView of pending updates
    self.tableView.beginUpdates() 
    defer { self.tableView.endUpdates() } 

    // Alter DataSource
    self.data[index.row] = "Changed Value" 
    self.tableView.reloadRowsAtIndexPaths([index], withRowAnimation: .Automatic)
}

【讨论】:

  • 虽然我想进一步为 Swift 2.3 添加语法:guard let label = sender.view as? UILabel else { print("错误不是标签"); return } let position = sender.locationInView(self.tableView) guard let index = self.tableView.indexPathForRowAtPoint(position) else { print("Error label not in tableView"); return } self.tableView.beginUpdates() defer { self.tableView.endUpdates() } self.data[index.row] = “Changed Value” self.tableView.reloadRowsAtIndexPaths([index], withRowAnimation: .Automatic)
  • 我已经添加了你的 Swift 2.3 版本 :-)
【解决方案2】:

细胞是可重复使用的。这意味着当您更改单元格上的值时,它将被更改并在该特定单元格标识符的所有重用中保持更改,直到您将其更改回来。

要解决您的问题,您可以在 cellForRowAtIndexPath 中设置“占位符”/DefaultText 文本,或者如果您有 subclassed 单元格,您可以在 prepareForReuse 方法。

【讨论】:

  • 我不太确定“它将被更改并在所有重用时保持更改”。如果您的数据源已更改,并且您将表格视图单元格滚动到视图之外,例如,当您返回时,cellForRow 会再次被调用,并且您的单元格配置代码很可能在该方法中,因此单元格的子视图将使用您提供的任何数据进行设置。
  • @StephenPaul 他正在直接更改文本,如果您查看他的代码,他没有更新任何数据源,并且更新的文本没有在他的数据源中引用。此外,他没有从任何数据源对 label.text 进行设置和赋值,他可能正在使用静态“占位符”。如果您更改了一次单元格属性的值,而您根本没有方法再次调用它,或者在您的 cellForRow 方法或 prepareForReuse 中更改它,您的单元格最终将得到更改后的值。
【解决方案3】:

你可以试试这个方法:

func labelTapped(recognizer: UITapGestureRecognizer){
    let dataCell: DataTableViewCell =  recognizer.view as! DataTableViewCell
    let indexPath = tableView.indexPath(for: dataCell)
    data[(indexPath?.row)!] = "changed value "
    self.tableView.reloadData()
}

【讨论】:

  • 正如 cmets 中所指出的,这不适用于可重复使用的单元格。重新使用单元格后,该单元格将收回原始 DataSource 值。
  • 它适用于我的日历,它有多个可重复使用的单元格。这是两行代码,我认为值得一试。 ;)
  • 这是一个直接修改标签的例子:imgur.com/a/G9Jjz,也许你的单元格永远不会离开屏幕——因此永远不会被重复使用?
  • 我明白你的意思,但这是持久存储的问题,以及你如何更新数据。他面临的问题是只更新一个标签,而不是更改其他单元格的文本。在我的日历中,我更新核心数据,然后使用NSFetchedResultsController 委托方法controllerDidChangeContent 更新reloadData()
  • @Emptyless 我的意思是手势识别器
猜你喜欢
  • 1970-01-01
  • 2021-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-20
  • 1970-01-01
相关资源
最近更新 更多