Swift iOS -How can I pass a value Obtained Directly from a within TableViewCell's SubClass to the TableView's didSelectRow?

不羁的心 提交于 2019-12-11 08:54:14

问题


Before anyone suggests to pull the Firebase data from within the PlayerController's viewWillAppear, I already know how to do that and if I did it that way I know how to pass the data to the ScoreController. In this situation I need to pull the data directly from within the cell and somehow pass the data back from there.

I have a tableView inside a PlayerController that displays the randomPower, name, and score of each player. Inside the tableView's cell I pull the name and score from Firebase using a function getScoreDataFromFirebase(). The function is located directly inside the tableView's PlayerCell and once I get the values from Firebase I initialize the cell's name and score outlets right then and there.

Inside the tableView's cellForRowAtIndexPath I call cell.getScoreDataFromFirebase() and everything works fine because both outlets display the correct values.

From that point on I have a ScoreController. When a tableView cell is chosen the score is sent to the ScoreController.

The problem is since I'm pulling the data directly from within the cell itself the only way I could pass the score (pulled from Firebase) to ScoreController was to 1st set a didSet score property inside the cell.

Still inside the cell when I pull the score data from Firebase 2nd I initialize the score property with it

3rd inside the tableView's cellForAtIndexPath I use an if let to pass the value from the cell's score property to the the tableData.

When I first try to send the indexPath of that tableData over to the ScoreController sometimes it's nil even though the cell's score property definitely has a value (I used to break points to check). If I select any of the very first few tableView cells that are visible they will have a nil value for the score property. However if I scroll further down through the cells and back up then those same cells will no longer have a nil score property.

What I found out was the if let statement was running before the Firebase code was pulled so the score property was nil for first few cells that are on scene. The odd thing is everything works fine once I start scrolling.

How can I pass a value pulled directly from a cell to the tableView's didSelectRow?

PlayerModel:

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

TableViewCell SubClass:

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
                           }
                      }
              }
         }
    }
}

TableView:

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

}

回答1:


You can achieve this using delegation :
Create a protocol

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

Your UIViewController should look like this :

PlayController : UITableViewDataSource, UITableViewDelegate, UpdateValueDelegate  
{
       var scoreDict:[String:String] = [:]
        //
       //  

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

In cellForRowAtIndexPath set cell.delegate = self and cell.row = indexPath.row

Your UITableViewCell should look like this :

class PlayerCell:UITableViewCell: UITableViewCell
{
    weak  var delegate: UpdateValueDelegate?
    var row: Int?
    //
    //
} 

Finally pass score from getScoreDataFromFirebase by calling delegate function:

func getScoreDataFromFirebase()
{
    //
    //
    delegate. changeValue(score: localScore, row: self.row)
}

Now you have the value in your viewController from where it can be easily passed to didSelectRow using the global dictionary ** scoreDict**.

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
    var score = self.scoreDict["\(indexPath.row)"]
   // Use score
}


来源:https://stackoverflow.com/questions/48773528/swift-ios-how-can-i-pass-a-value-obtained-directly-from-a-within-tableviewcell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!