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?
在有人建议从 PlayerController 的 viewWillAppear 中提取 Firebase 数据之前,我已经知道该怎么做,如果我那样做,我就知道如何将数据传递给 ScoreController。在这种情况下,我需要直接从单元格中提取数据并以某种方式从那里传回数据。
我在 PlayerController 中有一个 tableView,它显示每个玩家的随机功率、名称和分数。在 tableView 的单元格中,我使用函数 getScoreDataFromFirebase()
从 Firebase 中提取名称和分数。该函数直接位于 tableView 的 PlayerCell 内部,一旦我从 Firebase 获得值,我就会立即在那里初始化单元格的名称和分数出口。
在 tableView 的 cellForRowAtIndexPath 中,我调用 cell.getScoreDataFromFirebase()
并且一切正常,因为两个出口都显示正确的值。
从那时起,我有了一个 ScoreController。选择 tableView 单元格时,分数将发送到 ScoreController。
问题是因为我直接从单元格内部提取数据我可以将分数(从 Firebase 提取)传递给 ScoreController 的唯一方法是第一组单元格内的 didSet
得分 属性。
当我从 Firebase 2nd 中提取得分数据时,我仍在单元格内,我用它初始化得分 属性
tableView 的 cellForAtIndexPath 中的第 3 个我使用 if let
将单元格分数 属性 中的值传递给 tableData。
当我第一次尝试将该 tableData 的 indexPath 发送到 ScoreController 时,有时它为 nil,即使单元格的分数 属性 确实有一个值(我曾经断点来检查)。如果我 select 任何可见的前几个 tableView 单元格中的任何一个,它们的分数 属性 将具有零值。但是,如果我进一步向下滚动单元格并返回,那么那些相同的单元格将不再有零分数 属性。
我发现 if let
语句在提取 Firebase 代码之前是 运行,因此现场前几个单元格的分数 属性 为零。奇怪的是,一旦我开始滚动,一切正常。
如何将直接从单元格中提取的值传递给 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
}
您可以使用 委托 实现此目的:
创建一个 协议
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 = self 和 cell.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
}
在有人建议从 PlayerController 的 viewWillAppear 中提取 Firebase 数据之前,我已经知道该怎么做,如果我那样做,我就知道如何将数据传递给 ScoreController。在这种情况下,我需要直接从单元格中提取数据并以某种方式从那里传回数据。
我在 PlayerController 中有一个 tableView,它显示每个玩家的随机功率、名称和分数。在 tableView 的单元格中,我使用函数 getScoreDataFromFirebase()
从 Firebase 中提取名称和分数。该函数直接位于 tableView 的 PlayerCell 内部,一旦我从 Firebase 获得值,我就会立即在那里初始化单元格的名称和分数出口。
在 tableView 的 cellForRowAtIndexPath 中,我调用 cell.getScoreDataFromFirebase()
并且一切正常,因为两个出口都显示正确的值。
从那时起,我有了一个 ScoreController。选择 tableView 单元格时,分数将发送到 ScoreController。
问题是因为我直接从单元格内部提取数据我可以将分数(从 Firebase 提取)传递给 ScoreController 的唯一方法是第一组单元格内的 didSet
得分 属性。
当我从 Firebase 2nd 中提取得分数据时,我仍在单元格内,我用它初始化得分 属性
tableView 的 cellForAtIndexPath 中的第 3 个我使用 if let
将单元格分数 属性 中的值传递给 tableData。
当我第一次尝试将该 tableData 的 indexPath 发送到 ScoreController 时,有时它为 nil,即使单元格的分数 属性 确实有一个值(我曾经断点来检查)。如果我 select 任何可见的前几个 tableView 单元格中的任何一个,它们的分数 属性 将具有零值。但是,如果我进一步向下滚动单元格并返回,那么那些相同的单元格将不再有零分数 属性。
我发现 if let
语句在提取 Firebase 代码之前是 运行,因此现场前几个单元格的分数 属性 为零。奇怪的是,一旦我开始滚动,一切正常。
如何将直接从单元格中提取的值传递给 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
}
您可以使用 委托 实现此目的:
创建一个 协议
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 = self 和 cell.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
}