diff --git a/FirebaseStorage/Sources/StorageDownloadTask.swift b/FirebaseStorage/Sources/StorageDownloadTask.swift index 504056464d3..5bfe3ee4b50 100644 --- a/FirebaseStorage/Sources/StorageDownloadTask.swift +++ b/FirebaseStorage/Sources/StorageDownloadTask.swift @@ -85,7 +85,6 @@ open class StorageDownloadTask: StorageObservableTask, StorageTaskManagement { } private var fetcher: GTMSessionFetcher? - private var fetcherCompletion: ((Data?, NSError?) -> Void)? var downloadData: Data? // Hold completion in object to force it to be retained until completion block is called. var completionData: ((Data?, Error?) -> Void)? @@ -104,7 +103,7 @@ open class StorageDownloadTask: StorageObservableTask, StorageTaskManagement { self.fetcher?.stopFetching() } - func enqueueImplementation(resumeWith resumeData: Data? = nil) { + private func enqueueImplementation(resumeWith resumeData: Data? = nil) { dispatchQueue.async { [weak self] in guard let self = self else { return } self.state = .queueing @@ -153,32 +152,29 @@ open class StorageDownloadTask: StorageObservableTask, StorageTaskManagement { } } self.fetcher = fetcher - - // Capture self here to retain until completion. - self.fetcherCompletion = { [self] (data: Data?, error: NSError?) in - defer { - self.removeAllObservers() - self.fetcherCompletion = nil - } - self.fire(for: .progress, snapshot: self.snapshot) - - // Handle potential issues with download - if let error { + self.state = .running + Task { + do { + let data = try await self.fetcher?.beginFetch() + // Fire last progress updates + self.fire(for: .progress, snapshot: self.snapshot) + + // Download completed successfully, fire completion callbacks + self.state = .success + if let data { + self.downloadData = data + } + self.fire(for: .success, snapshot: self.snapshot) + } catch { + self.fire(for: .progress, snapshot: self.snapshot) self.state = .failed - self.error = StorageErrorCode.error(withServerError: error, ref: self.reference) + self.error = StorageErrorCode.error( + withServerError: error as NSError, + ref: self.reference + ) self.fire(for: .failure, snapshot: self.snapshot) - return } - // Download completed successfully, fire completion callbacks - self.state = .success - if let data { - self.downloadData = data - } - self.fire(for: .success, snapshot: self.snapshot) - } - self.state = .running - self.fetcher?.beginFetch { [self] data, error in - self.fetcherCompletion?(data, error as? NSError) + self.removeAllObservers() } } } diff --git a/FirebaseStorage/Sources/StorageUploadTask.swift b/FirebaseStorage/Sources/StorageUploadTask.swift index 48564b1d9b4..a0a4bea7eac 100644 --- a/FirebaseStorage/Sources/StorageUploadTask.swift +++ b/FirebaseStorage/Sources/StorageUploadTask.swift @@ -115,38 +115,36 @@ import Foundation // Process fetches self.state = .running + Task { + do { + let data = try await self.uploadFetcher?.beginFetch() + // Fire last progress updates + self.fire(for: .progress, snapshot: self.snapshot) + + // Upload completed successfully, fire completion callbacks + self.state = .success - self.fetcherCompletion = { [self] (data: Data?, error: NSError?) in - // Fire last progress updates - self.fire(for: .progress, snapshot: self.snapshot) + guard let data = data else { + fatalError("Internal Error: uploadFetcher returned with nil data and no error") + } - // Handle potential issues with upload - if let error { + if let responseDictionary = try? JSONSerialization + .jsonObject(with: data) as? [String: AnyHashable] { + let metadata = StorageMetadata(dictionary: responseDictionary) + metadata.fileType = .file + self.metadata = metadata + } else { + self.error = StorageErrorCode.error(withInvalidRequest: data) + } + self.finishTaskWithStatus(status: .success, snapshot: self.snapshot) + } catch { + self.fire(for: .progress, snapshot: self.snapshot) self.state = .failed - self.error = StorageErrorCode.error(withServerError: error, ref: self.reference) + self.error = StorageErrorCode.error(withServerError: error as NSError, + ref: self.reference) self.metadata = self.uploadMetadata self.finishTaskWithStatus(status: .failure, snapshot: self.snapshot) - return - } - // Upload completed successfully, fire completion callbacks - self.state = .success - - guard let data = data else { - fatalError("Internal Error: fetcherCompletion returned with nil data and nil error") - } - - if let responseDictionary = try? JSONSerialization - .jsonObject(with: data) as? [String: AnyHashable] { - let metadata = StorageMetadata(dictionary: responseDictionary) - metadata.fileType = .file - self.metadata = metadata - } else { - self.error = StorageErrorCode.error(withInvalidRequest: data) } - self.finishTaskWithStatus(status: .success, snapshot: self.snapshot) - } - self.uploadFetcher?.beginFetch { [weak self] (data: Data?, error: Error?) in - self?.fetcherCompletion?(data, error as NSError?) } } } @@ -202,7 +200,6 @@ import Foundation } private var uploadFetcher: GTMSessionUploadFetcher? - private var fetcherCompletion: ((Data?, NSError?) -> Void)? private var uploadMetadata: StorageMetadata private var uploadData: Data? // Hold completion in object to force it to be retained until completion block is called. @@ -247,7 +244,6 @@ import Foundation func finishTaskWithStatus(status: StorageTaskStatus, snapshot: StorageTaskSnapshot) { fire(for: status, snapshot: snapshot) removeAllObservers() - fetcherCompletion = nil } private func GCSEscapedString(_ input: String?) -> String? {