swift - 从 VC1 中的 firebase 检索用户数据并将其发送到 VC2 中的 TableView 以进行显示时出现问题
问题描述
我从 firebase firestore 检索所有数据时遇到问题(它跟踪一些用户信息,即标题、描述和 imageURL),然后从 firebaseStorage 下载图像,创建一个名为 Cella 的对象(标题:字符串,描述:字符串,图像: UIImage)。这个过程应该发生在一个循环中,然后为每个用户创建一个对象,并返回一个 Cella 对象数组,以传递给另一个 ViewController 并显示在它的 tableView 上。
我已经尝试修复完成处理程序,因为我认为它们是问题所在,然后我添加了一个 IBAction,它在执行 segue 时触发。
我尝试在其中检索数据的 ViewController(请注意,它位于 Navigation View Controller 中,并且 segue 是唯一的,当按下该按钮时会触发)。
class ViewController: UIViewController {
let firestoreUsersReference = Firestore.firestore().collection("users")
let storageReference = Storage.storage()
var cellaObjects : [Cella] = []
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
getDocumentsFromFirestore(firestoreReference: firestoreUsersReference) { (cellaArray) in
self.cellaObjects = cellaArray
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func getImagesDownloaded(reference: StorageReference, completion: @escaping (UIImage?,Error?)->()) {
reference.getData(maxSize: 10*1024*1024) { (data, error) in
guard error == nil, let data = data else {
completion(nil,error)
return
}
guard let image = UIImage(data: data) else {
completion(nil, FirebaseErrors.expectedImage)
return
}
completion(image,nil)
}
}
enum FirebaseErrors: Error {
case expectedImage
}
func getDocumentsFromFirestore (firestoreReference: CollectionReference, completion: @escaping ([Cella])->()) {
var cellaArray : [Cella] = []
firestoreUsersReference.getDocuments { (querySnapshot, err) in
if err != nil {
print("There has been an error \(String(describing: err?.localizedDescription))")
}
else {
for documents in querySnapshot!.documents {
print("\(documents.documentID) => \(documents.data())")
let data = documents.data()
let title = data["userTitle"] as! String
let description = data["userDescription"] as! String
let imageURL = data["userImageURL"] as! String
print("Title: \(String(describing: title)), Description: \(String(describing: description)), imageURL: \(imageURL)")
self.cellCreationProcess(title: title, description: description, imageURL: imageURL, completion: { (newCell) in
cellaArray.append(newCell)
})
}
completion(cellaArray)
}
}
}
func cellCreationProcess(title: String, description: String, imageURL: String, completion: @escaping (Cella) -> ()) {
let storagePath = Storage.storage().reference(forURL: imageURL)
self.getImagesDownloaded(reference: storagePath, completion: { (image, error) in
guard let image = image, error == nil else {
print(String(describing : error?.localizedDescription))
return
}
print("TITLE: \(String(describing: title)), IMAGE: \(image)")
let newCell = Cella(image: image, title: title, bodyMessage: description)
completion(newCell)
})
}
}
TableView 所在的 ViewController:
class ViewControllerForTable: UIViewController, UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let currentCell = tableView.cellForRow(at: indexPath) as! TableViewCell
let information = Information(title: currentCell.title.text!, description: currentCell.bodyText.text!, sellerImage: currentCell.CellImage.image!)
let destinationVC = self.storyboard?.instantiateViewController(withIdentifier: "ViewControllerDisplay") as! ViewControllerDisplay
destinationVC.dataPassed = information
self.navigationController?.pushViewController(destinationVC, animated: true)
}
@IBOutlet weak var UITableView: UITableView!
let image : UIImage = UIImage(named: "image1")!
var cells : [Cella] = []
override func viewDidLoad() {
super.viewDidLoad()
//states that this class is the delegate of the data and the object tableView within this VC
UITableView.delegate = self
UITableView.dataSource = self
//force sets each of the the tableView rows to have a height of 200
UITableView.rowHeight = 200
// Do any additional setup after loading the view.
}
//Function hardcoded that creates the 5 cells to test the app
//MARK - Table view settings
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//meaning my UITableView is going to have cells.count different rows
return cells.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//Gets each item singularly in order from the dictionary of cells
let cellFormat = cells[indexPath.row]
//You need to do this Nib thing because you created a xib file
let nib = UINib(nibName: String(describing: TableViewCell.self), bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "customCell")
// Says that it is going to create a reusable cell with the identifier from the XIB file and it is going to use the class TableViewCell to access its properties
let cellObject = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! TableViewCell
//Creates and assigns the values from the item in the dictionary to the CellFormat for them to be displayed in the custom cell
cellObject.setCell(cellFormatTaken: cellFormat)
// returns the final Cell Item
return cellObject
}
@IBAction func unwindToActivitieslList(sender: UIStoryboardSegue) {
let sourceViewController = sender.source as? ViewController
let activities = sourceViewController?.cellaObjects
cells = activities!
UITableView.reloadData()
}
}
------------------ 更新 ------------------ 我已删除
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
getDocumentsFromFirestore(firestoreReference: firestoreUsersReference) { (cellaArray) in
self.cellaObjects = cellaArray
}
}
并添加了 Button @IBAction func sardiniaNePressed(_ sender: UIButton) {
getDocumentsFromFirestore(firestoreReference: firestoreUsersReference) { (cellaArray) in
self.cellaObjects = cellaArray
self.performSegue(withIdentifier:"sardiniaNe",sender:nil)
}
}
我还按照善意的建议添加了调度。尽管如此,我仍然无法获得要显示的数据。我对按钮的另一个问题是,每当我单击它时,由于 VC 嵌入在导航控制器中,它们会创建目标 ViewController 的“副本”,并且它会在应用程序打开的整个过程中一直这样做,给我留下了许多重复的空行。
解决方案
您需要在外部调用它prepare(for segue:
(直接在按钮操作中)并完成执行 segue
getDocumentsFromFirestore(firestoreReference: firestoreUsersReference) { (cellaArray) in
self.cellaObjects = cellaArray
self.performSegue(withIdentifier:"segue",sender:nil)
}
同样在这里您需要DispatchGroup()
获取每个项目的图像是异步的
func getDocumentsFromFirestore (firestoreReference: CollectionReference, completion: @escaping ([Cella])->()) {
var cellaArray : [Cella] = []
firestoreUsersReference.getDocuments { (querySnapshot, err) in
if err != nil {
print("There has been an error \(String(describing: err?.localizedDescription))")
}
else {
let g = DispatchGroup()
for documents in querySnapshot!.documents {
g.enter()
print("\(documents.documentID) => \(documents.data())")
let data = documents.data()
let title = data["userTitle"] as! String
let description = data["userDescription"] as! String
let imageURL = data["userImageURL"] as! String
print("Title: \(String(describing: title)), Description: \(String(describing: description)), imageURL: \(imageURL)")
self.cellCreationProcess(title: title, description: description, imageURL: imageURL, completion: { (newCell) in
cellaArray.append(newCell)
g.leave()
})
}
g.notify(queue: .main, execute: {
completion(cellaArray)
})
}
}
}
推荐阅读
- azure - 是否有 ARM 模板可以在其下创建 ASE(应用服务环境)和多个 ASP(应用服务计划)
- python - Pyomo 在调用求解器时缺少自我
- python - 选择功能不能通过 Operadriver 工作,但可以在 Chromedriver 中工作
- azure - SSIS 包:找不到方法 Microsoft.WindowsAzure.Storage.Blob.CloudBlobClient
- unity3d - 无法向 UnityEvent 添加功能
- excel - 如何计算指数和幂趋势线类型的 R 平方值
- r - 无法向图表添加图例
- unpoly - 模态和抽屉的unpoly
- elixir - Elixir 自定义任务未显示在“混合帮助”中
- javascript - 获取 WebUSB API 中可用的 USB 设备列表