Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 21 additions & 25 deletions FirebaseStorage/Sources/StorageDownloadTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)?
Expand All @@ -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
Expand Down Expand Up @@ -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()
}
}
}
Expand Down
52 changes: 24 additions & 28 deletions FirebaseStorage/Sources/StorageUploadTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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?)
}
}
}
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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? {
Expand Down