Swift Tableview 从 Firebase 数据库加载数据
Posted
技术标签:
【中文标题】Swift Tableview 从 Firebase 数据库加载数据【英文标题】:Swift Tableview Load Data from Firebase Database 【发布时间】:2019-07-27 08:39:36 【问题描述】:我目前正在尝试在不同的表格视图中显示我的 Firebase 实时数据库中的数据。
在我的第一个 tableview 中,我加载了我的第一级数据库结构(这已经有效)。
现在我想看看用户在第一个 tableview 中选择了什么,然后在新的 TableView 中显示我的数据库的下一级。
我的第二个 TableViewController.swift 文件中有一个函数可以保存在第一个 TableView 的选定行中。
这样,我想将数据库中的下一个级别保存到一个数组中,以便这些数据将显示在我的第二个表视图中。然后,当我调试我的新数组时,我还会在新数组中看到正确的数据。但是,第二个 TableView 中并没有显示数据。
我猜这是因为在 TableView 加载之前数据还没有 100% 准备好。
你有小费吗?
Firebase 结构:
-sports
-Bicycle
-BMX
-Bike 1
-img: „bike1.png“
-text: „bike 1“
-Bike 2
-img: „bike2.png“
-text: „bike 1“
-Car
-Audi
-Car 1
-img: „car1.png“
-text: „car 1“
-Car 2
-img: „car2.png“
-text: „car 2“
FirstTableViewController:
import UIKit
import Firebase
class FirstTableViewController: UITableViewController
var categorie = [String]()
func loadData()
var ref: DatabaseReference!
ref = Database.database().reference()
ref.child("sports").observeSingleEvent(of: .value, with: snapshot in
if let sports = snapshot.value as? [String: Any]
for (title, _) in sports
self.categorie.append(title)
self.tableView.reloadData()
)
override func viewDidLoad()
loadData()
super.viewDidLoad()
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return categorie.count
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "sportCell")
cell?.textLabel?.text = categorie[indexPath.row]
return cell!
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
// Set the segue's identifier in the Storyboard
performSegue(withIdentifier: "firstToSecond", sender: self)
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
if segue.identifier == "firstToSecond"
guard let destination = segue.destination as? SecondTableViewController,
let indexPath = tableView.indexPathForSelectedRow else return
destination.detailedValue = categorie[indexPath.row]
SecondTableViewController:
import UIKit
import Firebase
class SecondTableViewController: UITableViewController
var detailedValue: String?
var secondArray = [String]()
func setIndex(value: String)
loadData(index: value)
func loadData(index: String)
var ref: DatabaseReference!
ref = Database.database().reference()
if (index != "")
ref.child("sports").child(index).observeSingleEvent(of: .value, with: snapshot in
if let sports = snapshot.value as? [String: Any]
for (title, _) in sports
self.secondArray.append(title)
self.tableView.reloadData()
)
override func viewDidLoad()
super.viewDidLoad()
if let detailedValue = detailedValue
loadData(index: detailedValue)
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return secondArray.count
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "sorteCell")
cell?.textLabel?.text = secondArray[indexPath.row]
return cell!
更新 1: 感谢@Jay Lee 提供上述代码。
更新 2:
【问题讨论】:
【参考方案1】:您不是将数据加载到屏幕上显示的SecondTableViewController
实例,而是加载到您在FirstTableViewController
的func tableView(_:=,cellForRowAt:)
方法中创建的新SecondTableViewController
实例。
日志是从您创建的多个实例中打印出来的。
这不是您想要的,因为每次在您的 FirstTableViewController
中显示一个新单元格时,您都会创建多个 SecondTableViewController
实例。
您应该获得对所显示的实际 SecondTableViewController
的引用并提供数据。
如果您使用故事板,您可以使用prepare(for:sender:)
来执行此操作。
我们有两个选择:使用委托设计模式提供从FirstTableViewController
到SecondTableViewController
的全部数据,或者只提供value
到SecondTableViewController
并将获取留给它。
根据您的代码,您可以在SecondTableViewController
中使用setIndex(value:)
方法提供SecondTableViewController
和value
,并在SecondTableViewController
加载后获取数据。
例如,在您的SecondTableViewController
:
class SecondTableViewController: UITableViewController
...
var detailedValue: String?
override func viewDidLoad()
super.viewDidLoad()
if let detailedValue = detailedValue
setIndex(value: detailedValue)
...
在你的FirstTableViewController
:
class FirstTableViewController: UITableViewController
...
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
// Set the segue's identifier in the Storyboard
performSegue(withIdentifier: "yourIdentifier", sender: self)
...
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
if segue.identifier == "yourIdentifier"
guard let destination = segue.destination as? SecondTableViewController,
let indexPath = tableView.indexPathForSelectedRow else return
destination.detailedValue = categories[indexPath.row]
但请注意,您的FirstTableViewController
中已经有要在SecondTableViewController
上显示的数据,因此您可能应该创建一个protocol
并将FirstTableViewController
设置为它的代表。
编辑: 你的 segue 不应该像这样连接: 但像这样:
【讨论】:
首先非常感谢您的帮助。我现在已经在我的代码中插入了你的建议(见上文)如果我现在点击“FirstViewController”中的“Bicylce”,我实际上会被重定向并看到预期的“BMX”。但是现在我会被转发两次(见更新2中的上图)当我点击图1中的“自行车”时打开(图2)然后自动切换到(图3)。您能否在这里给我一个提示,我仍然做错了什么?非常非常感谢。 我怀疑您的 segue 是从表格视图单元格连接到SecondTableViewController
的。如果是这种情况,您应该将 segue 从 FirstTableViewController
本身连接到 SecondTableViewController
。
天哪,你是我的救命稻草:P 效果很好。现在我终于可以继续了。也许我会再次与您联系:D
没问题!很高兴听到它有帮助。 :)
再次您好:P,我正在取得进展。然而,我现在发现了一个错误。我正在运行数据库顶层的单个子级并将它们添加到一个新数组中。然后当我打印我的数组时,顺序总是不同的。有时 ["Car", "Bicycle"] 也有 ["Bicycle", "Car"]。如何指定遵守订单?以上是关于Swift Tableview 从 Firebase 数据库加载数据的主要内容,如果未能解决你的问题,请参考以下文章
从 AppDelegate Swift 4 更新 tableView 行
Swift 3:tableView 复制从 Firebase 加载的图像
如何使用 Swift 从 tableview 和 sqlite3 中删除
SWIFT:从定义 tableView 到 tableViewCell 的 ViewController 通信数据