我正在尝试从我的Firebase数据库中检索Firebase中的数据集并将其显示在tableview中。要向前呈现它并能够查看放入Firebase服务器中的数据
我在Stackoverflow上尝试使用多个问题,但似乎没有任何效果,并且日志错误似乎始终相同 Log Error
Firebase树
Products {
dfkjsv4qc22aWE:{
name:"Apples",
weight:"1 Bag",
price:"$5.99",
imageUrl:"https://firebasestorage.googleapis.com/v0/b/randomImageapp.BlahBlask2233"
}
se04Fws444:{
name:"Flower",
weight:"Bouquet",
price:"$10.99",
imageUrl:"https://firebasestorage.googleapis.com/v0/b/randomImageapp.BlahBlask2233"
}
}
import UIKit
import Foundation
import Firebase
import FirebaseStorage
import FirebaseDatabase
class ProductListController: UIViewController {
@IBOutlet weak var productListTableView: UITableView!
var feeds = [ProductList]()
var dbRef :DatabaseReference!
var storage : Storage!
var dbRef: DatabaseReference!
var storage: StorageReference!
fileprivate var products: [ProductList] = []
{
didSet
{
productListTableView.reloadData()
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidLoad() {
super.viewDidLoad()
productListTableView.dataSource = self
productListTableView.delegate = self
dbRef = Database.database().reference()
storage = Storage.storage().reference()
readProducts()
printProducts()
}
var productsArrayDataSource = [ProductList]()
func readProducts() {
let productsRef = self.dbRef.child("products") //self.ref points to my firebase
productsRef.observe(.childAdded, with: { snapshot in
let aProduct = ProductList(withSnapshot: snapshot)
self.feeds.append(aProduct)
})
}
func printProducts() {
for product in self.feeds {
print(product.id!, product.name!)
}
}
extension ProductListController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return products.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ProductListCell") as!
ProductListCell
let details = products[indexPath.row]
cell.updateUI(with: details)
return cell
}
}
import Foundation
import UIKit
import Firebase
import FirebaseDatabase
class ProductList {
var name: String
var price: String
var weight: String
var imageUrl: String
init(withSnapshot: DataSnapshot) {
self.name = withSnapshot.childSnapshot(forPath: "name").value as? String ?? "No Name"
self.price = withSnapshot.childSnapshot(forPath: "price").value as? String ?? "No Price"
self.weight = withSnapshot.childSnapshot(forPath: "weight").value as? String ?? "No Weight"
self.imageUrl = withSnapshot.childSnapshot(forPath: "imageUrl").value as? String ?? "No ImageUrl"
}
}
import UIKit
import SDWebImage
import Firebase
class ProductListCell: UITableViewCell {
@IBOutlet weak var productImage: UIImageView!
@IBOutlet weak var productName: UILabel!
@IBOutlet weak var weight: UILabel!
@IBOutlet weak var price: UILabel!
func updateUI(with productList: ProductList) {
productName.text = productList!.name
price.text = productList!.price
weight.text = productList!.weight
productImage.text = productList!.imageUrl
}
override func layoutSubviews() {
super.layoutSubviews()
}
}
编辑:这是我到目前为止在错误中所遇到的问题error 2,似乎它比编码错误更像是firebase问题
答案 0 :(得分:1)
请让我看看您能否朝正确的方向前进。这个问题有两个部分,因此我将深入研究Firebase部分。如果在那之后不显示tableView,那是一个tableView委托问题,但是看起来您的代码还可以。
第一个要解决的问题是Firebase结构-嗯,不是结构,而是键。来自文档
如果您创建自己的密钥,则它们必须是UTF-8编码的,可以是 最大768个字节,并不能包含。,$,#,[,],/,或ASCII 控制字符0-31或127。不能使用ASCII控制 中的值字符本身,无论是。
因此您可以看到密钥中包含非法字符。通常,最佳做法是允许Firebase使用.childByAutoId()创建密钥。
看一下ProductList类,这确实很好,但您可能还想跟踪Firebase密钥。因此,例如,用户选择了它,您就会知道它是哪个项目。所以我刚刚添加了一个关键属性
class ProductList {
var key: String
var name: String
var price: String
var weight: String
var imageUrl: String
init(withSnapshot: DataSnapshot) {
self.key = withSnapshot.key
self.name = withSnapshot.childSnapshot(forPath: "name").value as? String ?? "No Name"
self.price = withSnapshot.childSnapshot(forPath: "price").value as? String ?? "No Price"
self.weight = withSnapshot.childSnapshot(forPath: "weight").value as? String ?? "No Weight"
self.imageUrl = withSnapshot.childSnapshot(forPath: "imageURL").value as? String ?? "No ImageUrl"
}
}
如评论中所述,子节点名称区分大小写,因此我还更新了代码以读取 imageURL 节点(以匹配您的结构),而不是 imageUrl
然后是一个用于存储产品的类数组(如代码中所示)
var feeds = [ProductList]()
然后使用代码实际读取节点并填充feed数组。
func readProducts() {
let productsRef = self.ref.child("Products") //self.ref points to my firebase
productsRef.observe(.childAdded, with: { snapshot in
let aProduct = ProductList(withSnapshot: snapshot)
self.feeds.append(aProduct)
})
}
这里要注意的是,我们正在使用observe.childAdded阅读。 .childAdded最初在每个子节点上进行一次迭代,而.observe在该节点上留下一个观察者,该观察者将在每次添加新子节点时在闭包中调用代码。
然后稍后,我们要查看数组中的内容
func printProducts() {
for product in self.feeds {
print(product.key, product.name)
}
}
,然后调用printProducts时的输出
dfkjsv4qc22aWE Apples
se04Fws444 Flower
我从该答案的结构中删除了非法字符,但.childByAutoId()再次是您的朋友。它始终有效,始终唯一,并将密钥与其包含的数据分开。
对此的最后想法是:什么时候重新加载tableView。有两种选择,但一种选择是使用.value用.observeSingleEvent读取一次数据,然后遍历代码中的子节点,填充数组(与问题中的内容类似),然后重新加载tableView。 / p>
第二个选项是利用.value事件始终在其他事件(例如.childAdded)之后最后触发。因此,您可以使用childAdded填充数组,还可以添加一个.value事件,该事件将在添加所有子节点之后触发,然后重新加载tableView。 SO上有许多该过程的示例。哦,现在是一个