How to Perform an Action Only After Data Are Downloaded from Firebase

How to wait till download from Firebase Storage is completed before executing a completion swift

Since loading the image data is an asynchronous operation, any code that needs to run after the images have loaded will need to be inside the completion handler, be called from there, or be otherwise synchronized.

A simple way is to count the number of images that have completely loaded, and call once it matches the length of the array:

imageArray.removeAll()

for imageRef in products! {

let storageRef = self.storage.reference(withPath: imageRef.image!)

storageRef.getData(maxSize: 1 * 1024 * 1024) { [self] data, error in

if let error = error {
print (error)
} else {

//Image Returned Successfully:
let image = UIImage(data: data!)

//Add Images to the Array:
imageArray.append(image!)

// br> if (imageArray.count == products!.count) {
completion (true)
}
}
}
}

How to execute code directly after Firebase finishes downloading?

these network requests run async so any code after them will continue to run while the network request is being completed.

you should move updateCards.append(cards) inside the inner closure so it doesn't get called until that second closure finishes, then if you have other code you need to run when this is complete you can either move it inside of this function or use a closure with a completion handler to make sure all network requests are completed before you run any more code the relies on the response.

getCardData { [weak self] in
// do whatever you need to do after completion
}

func getCardData(_ completion: () -> ()) {
print("Feed: button donwloading cards")
//self.databaseButton.setTitle("Downloading New Cards...", for: .normal)
ref.observe(.value, with: { snapshot in
print("Feed: Checking for new cards from firebase")
for item in snapshot.children {
// Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
cardRef.data(withMaxSize: 1 * 1024 * 1024) { (data, error) -> Void in
if (error != nil) {
// Uh-oh, an error occurred!
print("Feed: error occured")
print(error)
completion() // this is where you would normally throw an error or have a closure that accepts an optional error you would pass in to know it failed
} else {
// Data for "images/island.jpg" is returned
cards.imageName = data!
print("Feed: downloaded \(cards.name)")
updateCards.append(cards);
completion()// now you know all network requests are complete
}
}
}
})
}

How to do some action when image from firebase is stored in storage

StorageReference's getFile(File destinationFile) method returns a FileDownloadTask object which is actually a Task.

To solve you can use Tasks's whenAllSuccess(Collection> tasks) method like this:

List<Task<?>> tasks = new ArrayList<>();
tasks.add(downloadRef.getFile(file1));
tasks.add(downloadRef.getFile(file2));
tasks.add(downloadRef.getFile(file3));
//And so on
Tasks.whenAllSuccess(tasks).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
@Override
public void onSuccess(List<Object> list) {
//Do what you need to do with your list
for (Object object : list) {
//Show images
}
}
});

How does control flow work when retrieving Information from Firebase?

It's the logic of asynchronous calls

print("1") // empty
refBluetezeit.child("Februar").observeSingleEvent(of: .value, with: { snapshot in

print("3") // empty
for plant in snapshot.children {
self.ergebnisBluetezeit.insert((plant as AnyObject).value)
}
print(ergebnisBluetezeit) // not empty
})

print("2") // empty

the value is empty until the request finishes regardless of where in code ordering you run the print , as the numbering above in order 1 , 2 , 3 to know when it finishes you can use completions like

func getData(completion:@escaping() -> ()) {
let refBluetezeit = rootRef.child("Pflanzen").child("Eigenschaften").child("Blütezeit")
refBluetezeit.child("Februar").observeSingleEvent(of: .value, with: { snapshot in
for plant in snapshot.children {
self.ergebnisBluetezeit.insert((plant as AnyObject).value)
}
completion()
})
}

And call

getData {
print(ergebnisBluetezeit)
}

Firebase: How to implement take action only when another device is online ?

You already seem to have the best approach with built-in primitives, i.e. Firebase's presence system. One note on the onDisconnect though: it will only take that long to detect a dirty disconnect (app crashes, network connection lost, etc). In the case of a clean disconnect (app is closed), the onDisconnect should fire almost immediately.

If the way the onDisconnect behaves is not good enough for your needs, you will need to implement the rest inside your app.

The first thing that came to mind is an active keep-alive, which seems to be what you already use in #2. Given that you want a latency of at most 3 seconds, your 2 second keep-alive ping seems like a reasonable interval.

This will indeed increase your bandwidth usage. Given your use-case and the way the platform works, I don't see any other way to implement it though.



Related Topics



Leave a reply



Submit