Hi,
Completion handler did work for me in a different case, but here I am facing the same issue again and completion handler is not giving the expected result.
Since I am new to Swift I am not sure if I have implemented it correctly.
Here I am trying to download images based on a list of names from Firestore, and then adding them to a resource group.
I am expecting when the statement trackedImages = trackedImages.union(self.newReferenceImages) executes, newReferenceImages should have the downloaded images.
But it gets executed before the downloading is completed.
Please help.
func downloadArResources(listOfImages imageList: [String] ){
if !imageList.isEmpty {
for imageName in imageList {
print("Image working on: \(imageName)")
downloadAndAddToSet(name: imageName){
if var trackedImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: Bundle.main){
trackedImages = trackedImages.union(self.newReferenceImages)
print("new Bundle images = \(trackedImages.description)")
}
}
}
}
}
func downloadAndAddToSet(name imageName: String, completion: @escaping () -> Void){
let FIRImageName = self.root.child("MagicFrame/\(self.userName)/images/\(imageName).jpg")
FIRImageName.getData(maxSize: 5 * 1024 * 1024) { data, error in
if let error = error {
print("Error in downloading image: \(error)")
} else {
if let image = UIImage(data: data!){
if let cgimage = image.cgImage {
let newImage = ARReferenceImage(cgimage, orientation: .up, physicalWidth: 0.2)
newImage.name = imageName
self.newReferenceImages.insert(newImage)
}
}
}
}
completion()
}
Post
Replies
Boosts
Views
Activity
Thanks @blueturtle I have a much better understanding of how the completionHandler works.
I have tried implementing it accordingly and it did work, but I am still facing the same problem when I use it in calls between classes.
func refreshResources(forUser username: String, ARresourceReference imagesPresent: Set<ARReferenceImage>, completion: @escaping (Set<ARReferenceImage>) -> Void) {
self.userName = username
self.newReferenceImages = imagesPresent
getListandDownload()
DispatchQueue.main.async() {
completion(self.newReferenceImages)
}
}
Here getListandDownload() is a function of class CheckForDownloads that will perform some logic, download images and add them to newReferenceImages. Although all this takes some time (depends on network speed) it is working fine with the use of completionHandler.
getListandDownload() is being called from a different class ARViewController's viewWillAppear method
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let configuration = ARImageTrackingConfiguration()
guard let trackedImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: Bundle.main) else{
print("Problem in initializing AR Resources bundle")
return
}
self.checkForDownloads.refreshResources(forUser: self.username, ARresourceReference: trackedImages) { imageSet in
configuration.trackingImages = imageSet
configuration.maximumNumberOfTrackedImages = 1
// Run the view's session
self.sceneView.session.run(configuration)
}
}
Here I am expecting that only after getListandDownload() is completed, the completion(self.newReferenceImages) should be called that will set the configurations and run the session.
But what is happening now is that the completionHandler runs way sooner and debug log shows that the downloading is happening afterwards.
I also tried using
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
completion(self.newReferenceImages)
}
But it fails if the downloading takes more than 5 seconds, not what I am looking for.