I want to get some data from firebaseFirestore and download an image URL from firebaseStorage, while preparing for my segue that will bring the user to the TableViewController, where they will be displayed. Even when using some nested completion handlers (perhaps I made the code too longs), I'm still not able to perform my asyncronous tasks in order, thus rushing too early to the segue. For simplicity I'm using the single segue (no identifiers). In the ViewControllerForTable I have stated a variable var cells : [Cella] = [] globally.
let firestoreUsersReference = Firestore.firestore().collection("users")
let storageReference = Storage.storage()
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationVC = segue.destination as! ViewControllerForTable
prepareDataForSegue(firestoreReference: firestoreUsersReference) { (cella) in
destinationVC.cells = cella
print(destinationVC.cells)
}
}
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 prepareDataForSegue (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 {
self.getDocumentsFromFirestore(querySnapshot: querySnapshot, completion: { (title, description, image) in
let newCell = Cella(image: image, title: title, bodyMessage: description)
print("NEW CELL : \(newCell)")
cellaArray.append(newCell)
})
}
}
completion(cellaArray)
}
func getDocumentsFromFirestore (querySnapshot: QuerySnapshot?, completion: @escaping (String,String,UIImage)->()) {
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)")
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)")
completion(title!, description!, image)
})
}
}
If I understand your question correctly, here what you need to do:
Disconnect the segue for the button in your storyboard.
In the IBAction function for the button, do your prepareDataForSegue
work
Once the completion handler is called, call performSegue
, which will call the prepareSegue
, where you can assign the downloaded cella.
This should load the tableVC only when the data is available.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.