0

Need help in figuring out why my function is not executing when I thought it should but it executed after the completion block in the code. I am fairly new to Xcode so please excuse me if things sound confusing here. Below is my code.

class ImageDownloader{

typealias completionHandler = (Result<Set<ARReferenceImage>, Error>) -> ()
typealias ImageData = (image: UIImage, orientation: CGImagePropertyOrientation, physicalWidth: CGFloat, name: String)

static let URLDic = [ReferenceImagePayload]()


class func getDocumentData(completion:@escaping ([ReferenceImagePayload]) -> ()) {
    var documentCollection: [ReferenceImagePayload] = []
    db.collection("Users").getDocuments {(snapshot, error) in
        if error == nil && snapshot != nil {
            var index = 0
            for document in snapshot!.documents {
                let loadData = document.data()
                index += 1
                if loadData["Target URL"] != nil {
                    let url = loadData["Target URL"]
                    let urlString = URL(string: "\(String(describing: url ?? ""))")
                    let urlName = loadData["Target Image"]
                    documentCollection.append(ReferenceImagePayload(name: urlName as! String, url: urlString!))
                    if snapshot!.documents.count == index {
                        // After finished, send back the loaded data
                        completion(documentCollection)
                    }
                }
            }
          }
    }
}


static var receivedImageData = [ImageData]()


class func downloadImagesFromPaths(_ completion: @escaping completionHandler) {
    

// THE LINE BELOW WHERE I CALL THE FUNCTION IS NOT EXECUTED WHEN THIS CLASS IS INITIALLY CALLED. BUT AS THE CODE RUNS, THIS LINE BELOW IS EXECUTED AFTER THE COMPLETIONOPERATION = BLOCKOPERATION IS COMPLETED.

    let loadedDataDic: () = getDocumentData { (URLDic) in
        print(URLDic.self, "Got it")
    }


    let operationQueue = OperationQueue()

    operationQueue.maxConcurrentOperationCount = 6
    
    let completionOperation = BlockOperation {
        OperationQueue.main.addOperation({
        completion(.success(referenceImageFrom(receivedImageData)))

// LINE "let loadedDataDic: () = getDocumentData" ONLY GOT EXECUTED AT THIS POINT

        })
    }



    URLDic.forEach { (loadData) in

            let urlstring = loadData.url
            
            let operation = BlockOperation(block: {

                do{
                    let imageData = try Data(contentsOf: loadData.url)
                    print(imageData, "Image Data")

                    if let image = UIImage(data: imageData){

                        receivedImageData.append(ImageData(image, .up, 0.1, loadData.name))
            
                    }
                    }catch{

                        completion(.failure(error))
                    }
                })
          
                completionOperation.addDependency(operation)
            }
    
    operationQueue.addOperations(completionOperation.dependencies, waitUntilFinished: false)
    operationQueue.addOperation(completionOperation)

}

}

Athena
  • 31
  • 2
  • Can you be a bit clearer about what you expect? Since you're using asynchronous routines, it's hard to predict the order of execution. – Phillip Mills Oct 22 '20 at 16:53
  • @PhillipMills I expect the line "let loadedDataDic: () = getDocumentData { (URLDic) in ...." to run and execute the function getDocumentData as soon as "class func downloadImagesFromPaths" was called. Instead, it was like skipped over and only executed after the "let completionOperation = BlockOperation " completed. – Athena Oct 23 '20 at 04:20
  • That's not how async works. The function is *called* when you expect but the code inside executes whenever the `getDocuments` method finishes. – Phillip Mills Oct 23 '20 at 13:03
  • @PhillipMills I have much to learn. Thank-you for the explanation. Any suggestions on what I should do? – Athena Oct 23 '20 at 13:33
  • You need to isolate all the work that depends on having you document collection complete. Best is to then do that work inside the completion handler that you pass to `getDocumentData`. The other (older) style would be to post a notification when the collection is done and do the work in response to the notification. – Phillip Mills Oct 23 '20 at 13:44
  • Thank-you @PhillipMills . I will give that a shot :) – Athena Oct 23 '20 at 13:53

0 Answers0