ewang
ewang

Reputation: 506

Perform an Action After Multiple Asynchronous Functions Finish In Swift

I'm trying to download multiple files from Firebase Storage and add them into a textView. I want to download all files from Firebase Storage asynchronously using the function DownloadFile before the function addFilesIntoNote is called. I have tried doing this using Dispatch Groups:

override func viewDidLoad() {
    let group = DispatchGroup()

    DispatchQueue.main.async {
        if let attributes = self.noteAttributes {
            for attribute in attributes {
                group.enter()
                self.downloadFile(fileName: attribute.fileName) {
                    group.leave()
                }
            }
        }
    }

    group.notify(queue: .main) {
        self.addFilesIntoNote()
    }
}

func downloadFile(fileName: String, completionHandler: @escaping () -> Void) {
    let localURL = DocumentsDirectory.appendingPathComponent(fileName)
    let filePath = rtfNote!.noteID! + "/" + fileName
    let fileRef = storage.reference(withPath: filePath)

    if !fileManager.fileExists(atPath: localURL.path) {
        let downloadTask = fileRef.write(toFile: localURL) { url, error in
            if let error = error {
                print("error")
            } else {
                completionHandler()
            }
        }
    }
}

However, it still keeps calling the addFilesIntoNote function before all of the files are downloaded. How do I make sure that all files fully downloaded before calling the addFilesIntoNote function?

Upvotes: 1

Views: 337

Answers (1)

Jawad Ali
Jawad Ali

Reputation: 14427

Fire completion handler even if error occurred and you don't need main queue

change your code like this

override func viewDidLoad() {
    let group = DispatchGroup()

        if let attributes = self.noteAttributes {
            for attribute in attributes {
                group.enter()
                self.downloadFile(fileName: attribute.fileName) {
                    group.leave()
                }

        }
    }

    group.notify(queue: .main) {
        self.addFilesIntoNote()
    }
}

func downloadFile(fileName: String, completionHandler: @escaping () -> Void) {
    let localURL = DocumentsDirectory.appendingPathComponent(fileName)
    let filePath = rtfNote!.noteID! + "/" + fileName
    let fileRef = storage.reference(withPath: filePath)

    if !fileManager.fileExists(atPath: localURL.path) {
        let downloadTask = fileRef.write(toFile: localURL) { url, error in
            if let error = error {
                print("error")

            } 

             completionHandler()
        }
    }
}

Upvotes: 3

Related Questions