【问题标题】:Retrieving IndexPath of UITableView cell with UIButton when touched触摸时使用 UIButton 检索 UITableView 单元格的 IndexPath
【发布时间】:2018-06-24 10:07:34
【问题描述】:

当点击单元格中的按钮时,我正在努力如何检索 UITableViewCell 的 indexPath。我正在为按钮使用典型的委托代码。我已经用谷歌搜索并对此进行了实验,但我无法得到它。这是我的自定义 Tableview 单元格代码:

import UIKit

protocol MainTableViewCellDelegate {
    func tappedReport(id: String)
}

class MainTableViewCell: UITableViewCell {

    @IBOutlet weak var cellView: UIView!
    @IBOutlet weak var userLabel: UILabel!
    @IBOutlet weak var timeLabel: UILabel!
    @IBOutlet weak var postLabel: UILabel!

    var postItem: PostData!
    var delegate: MainTableViewCellDelegate?

    func setPost(post: PostData) {
        postItem = post
        let ourPost = postItem.postId
        print(ourPost)
    }

    @IBAction func reportButton(_ sender: UIButton) {
        delegate?.tappedReport(id: postItem.postId)
        //print("Reported post ID: \(postItem.postId)")
    }
}

// View controller/ cellforRowat


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! MainTableViewCell
        cell.postLabel.text = posts[indexPath.row].message
        cell.textLabel?.adjustsFontSizeToFitWidth = true
        cell.layer.cornerRadius = 8
        cell.userLabel.text = posts[indexPath.row].username

        cell.delegate = self
        cell.getIndexPath()
}

extension ViewController: MainTableViewCellDelegate {
    func tappedReport(id: String) {

        print("Hi")
        AlertController.showAlert(inViewController: self, title: "Report", message: "Report button tapped.")
    }
}

还有什么想法?

【问题讨论】:

  • 点击单元格中的按钮时会发生什么?您是否遇到了您不想要的错误或行为?看来,如果您尝试识别被窃听的单元格,那么使用标准 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 将是最简单的方法。然后,您可以轻松获取其中按钮的属性以发送到您的 tappedReport 方法。
  • 实际上 Kane Cheshire 的答案有效,但由于某种原因,当我点击按钮时它一直保持 nil 。如果它取出'postItem.postId',并用随机(“hi”)替换它,那么它工作正常。我现在也正在获取 indexPath,所以我想我将能够以不同的方式找到 .postId。
  • 不相关,但您可能希望将您的协议定义为class 协议(例如protocol MainTableViewCellDelegate: class { ... })并将您的delegate 定义为weak(例如weak var delegate: MainTableViewCellDelegate?)。否则,您将有一个强大的参考周期。

标签: swift uibutton tableview


【解决方案1】:

如果您将单元格作为委托调用的一部分传回,您可以向表格视图询问它的索引路径。

定义委托协议:

protocol MainTableViewCellDelegate: class {
    func cell(_ cell: MainTableViewCell, didTapReport reportID: String)
}

在您的单元格中,定义被点击的报告按钮的处理程序并通知代理:

@IBAction func reportButton(_ sender: UIButton) {
    delegate?.cell(self, didTapReport: postItem.postID)
}

然后在视图控制器中(根据您的代码,这是您的单元格的委托):

func cell(_ cell: MainTableViewCell, didTapReport reportID: String) {
    let indexPath = tableView.indexPath(for: cell)
    // Do something with the index path
}

因为该单元格可能没有索引路径(您可以将任何单元格传递给该参数),所以返回类型是可选的,因此您必须在使用之前检查 indexPath 不是 nil。所以你可能需要做类似的事情

guard let indexPath = tableView.indexPath(for: cell) else { return }

【讨论】:

  • 感谢您的评论,但 'delegate?.cell(self, didTapReport: postItem.postID)' 去哪儿了?
  • @JackDerbis 这是调用其代表的单元格。它进入您单元格的 reportButton 方法,代替当前的委托调用。
  • @JackDerbis 请不要忘记,如果答案已经解决了您的问题,您应该通过单击答案左侧的复选标记来接受最佳答案。这让人们知道已经找到了解决方案。
【解决方案2】:

在 UITableViewCell 子类中还有另一个选项不使用委托或 IB 操作。您可以将此方法添加为 UIView 扩展

extension UIView {

    func superview<T: UIView>(of viewType: T.Type) -> T? {
        if superview == nil {
            return nil
        }

        if let view = superview as? T {
            return view
        }

        return superview?.superview(of: viewType)
    }
}

并像这样在视图控制器中使用它

@IBAction func actionTapButton(_ sender: UIButton) {
    guard
        let cell = sender.superview(of: YourCustomCell.self),
        let row = tableView.indexPath(for: cell)?.row
    else {
        return
    }

    //...
}

【讨论】:

    【解决方案3】:

    您可以在单元格内创建索引路径的属性,并在 cellForRow 方法中设置单元格的索引路径。

    比按钮点击只需使用 self.indexPath。

    也许这会解决你的问题

    【讨论】:

    • 不要这样做。此解决方案在可以添加、删除或移动行的表视图中失败。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多