Swift iOS - 如何将直接从 TableViewCell 的子类中获取的值传递给 TableView 的 didSelectRow?

Posted

技术标签:

【中文标题】Swift iOS - 如何将直接从 TableViewCell 的子类中获取的值传递给 TableView 的 didSelectRow?【英文标题】:Swift iOS -How can I pass a value Obtained Directly from a within TableViewCell's SubClass to the TableView's didSelectRow? 【发布时间】:2018-02-13 18:41:56 【问题描述】:

在有人建议从 PlayerController 的 viewWillAppear 中提取 Firebase 数据之前,我已经知道该怎么做,如果我这样做了,我就知道如何将数据传递给 ScoreController。在这种情况下,我需要直接从单元格中提取数据,然后以某种方式将数据从那里传回。

我在 PlayerController 中有一个 tableView,它显示每个玩家的 randomPower、name 和 score。在 tableView 的单元格中,我使用函数 getScoreDataFromFirebase() 从 Firebase 中提取名称和分数。该函数直接位于 tableView 的 PlayerCell 内部,一旦我从 Firebase 获取值,我就会立即初始化单元格的名称和得分点。

在 tableView 的 cellForRowAtIndexPath 中,我调用了cell.getScoreDataFromFirebase(),一切正常,因为两个出口都显示了正确的值。

从那时起,我有了一个 ScoreController。选择TableView单元格时,分数将发送到ScoreController。

问题是因为我直接从单元格本身中提取数据,我可以将分数(从 Firebase 中提取)传递给 ScoreController 的唯一方法是首先设置 didSet 分数单元格内的属性。

当我从 Firebase 中提取分数数据时仍在单元格内 2nd 我用它初始化 score 属性

tableView 的 cellForAtIndexPath 中的第三个我使用 if let 将值从单元格的 score 属性传递到 tableData。

当我第一次尝试将该 tableData 的 indexPath 发送到 ScoreController 时,有时它为零,即使单元格的 score 属性肯定有一个值(我曾经断点检查)。如果我选择前几个可见的 tableView 单元格中的任何一个,它们的 score 属性将具有 nil 值。但是,如果我进一步向下滚动单元格并向上滚动,那么这些相同的单元格将不再具有 nil score 属性。

我发现if let 语句在提取 Firebase 代码之前正在运行,因此现场前几个单元格的 score 属性为零。奇怪的是,一旦我开始滚动,一切正常。

如何将直接从单元格中提取的值传递给 tableView 的 didSelectRow?

玩家模型:

class PlayerModel
   name:String?
   score:String?
   randomPower:String?

TableViewCell 子类:

class PlayerCell:UITableViewCell
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var scoreLabel: UILabel!
    @IBOutlet weak var randomPowerLabel: UILabel!

    internal var score: String?
        didSet
            print("**********\(score ?? "*********")")
        
    

    override func prepareForReuse() 
         super.prepareForReuse()
         nameLabel.text = " "
         scoreLabel.text = " "
    

    func getScoreDataFromFirebase()

         let scoreRef = usersRef?.child("score")

         scoreRef?.observe( .value, with: 
              (snapshot) in

              for child in snapshot.children

                  let user = child as! DataSnapshot

                      for player in user.children

                           let eachPlayer = player as! DataSnapshot

                           if let dict = eachPlayer.value as? [String:Any]

                                 let name = dict["name"] as? String ?? " "
                                 let score = dict["score"] as? String ?? " "

                                 self.nameLabel.text = name
                                 self.scoreLabel.text = score

                                 self.score = score
                           
                      
              
         
    

表格视图:

class PlayerController: UITableViewDataSource, UITableViewDelegate

@IBOutlet weak fileprivate var tableView: UITableView!

var players = [PlayerModel]() // this array is populated with data from a previous vc. The number of players in the array are the same exact number of players that's pulled from the getScoreDataFromFirebase() function

override func viewDidLoad() 
    super.viewDidLoad()
    tableView.reloadData()


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
     return players.count


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "PlayerCell", for: indexPath) as! PlayerCell

     let cellData = players[indexPath.row]     

     cellData.randomPowerLabel.text = cellData.power

     cell.getScoreDataFromFirebase()

     if let score = cell.score
        cellData.score = score
     

     return cell


func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 

    guard let indexPath = tableView.indexPathForSelectedRow else  return 

    let scoreVC = storyboard?.instantiateViewController(withIdentifier: "ScoreController") as! ScoreController

    scoreVC.score = players[indexPath.row].score


【问题讨论】:

你将特定行的数据移动到下一个VC @KhawarIslam 将数据移动到下一个 vc 不是问题。我在 didSelectRow scoreVC.score = player[indexPath.row].score 中这样做。问题是我需要从单元格 getScoreDataFromFirebase() 函数中提取的分数中设置 player[indexPath.row].score 【参考方案1】:

您可以使用 delegation 实现此目的: 创建一个协议

protocol UpdateValueDelegate: class 
    func changeValue(score: String, row: Int)
  

您的UIViewController 应该如下所示:

PlayController : UITableViewDataSource, UITableViewDelegate, UpdateValueDelegate  

       var scoreDict:[String:String] = [:]
        //
       //  

      func changeValue(score: String, row: Int)
      
            self.scoreDict["\(row)"] = score
      
  

cellForRowAtIndexPath 中设置 cell.delegate = selfcell.row = indexPath.row

您的UITableViewCell 应该如下所示:

class PlayerCell:UITableViewCell: UITableViewCell

    weak  var delegate: UpdateValueDelegate?
    var row: Int?
    //
    //
 

最后通过调用委托函数从 getScoreDataFromFirebase 传递分数:

func getScoreDataFromFirebase()

    //
    //
    delegate. changeValue(score: localScore, row: self.row)

现在您在 viewController 中有了值,可以使用全局字典 ** scoreDict** 轻松将其传递给 didSelectRow

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

    var score = self.scoreDict["\(indexPath.row)"]
   // Use score

【讨论】:

谢谢,我会尝试一下。我没有尝试委托方法,因为我担心错误的数据会传递给单元格。给我几个 当然。另一件事。我在上面采用了行变量。您可能应该使用一个整数数组,因为每个单元格都会调用 getScoreDataFromFirebase。因此,要跟踪单元格行,您需要将其设置在数组中。 嗯,我从没想过,这对我来说实际上是新的,但它是有道理的,因为它可以跟踪所有内容。我必须消化它。谢谢。一旦我尝试了代码,如果有问题,我会回复你,但如果它很好,我会选择它作为答案。 编辑了我的答案。我已经演示了使用集合来存储行和分数并将其传递。 像魅力一样工作!我喜欢您使用 scoreDict 来跟踪行数据和随附的 scoreValue 的方式。确实很好:) 谢谢!!!

以上是关于Swift iOS - 如何将直接从 TableViewCell 的子类中获取的值传递给 TableView 的 didSelectRow?的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 中使用 Swift 保存 PDF 文件并显示它们

如何从 swift 中的按钮选项中删除 uitableviewcell?

如何将字节从 Swift (iOS) 传递到 Kotlin 通用模块?

无法在 View Controller iOS Swift 中显示 TabBar

如何在swift ios中自动将光标从一个文本字段移动到另一个文本字段?

如何使用 swift 从 iOS 设备上传文件(到 REDCap)